| 269 | if (request.voice.has_value() && request.voice->speaker.has_value() && |
| 270 | request.voice->speaker->audio.has_value()) { |
| 271 | reference_audio = *request.voice->speaker->audio; |
| 272 | } |
| 273 | const VoxCPM2EncodedPrompt *prompt = |
| 274 | encoded_prompt_for_request(request.audio_input, prompt_text, |
| 275 | reference_audio); |
| 276 | |
| 277 | runtime::TaskResult result; |
| 278 | double generator_ms = 0.0; |
| 279 | double decoder_ms = 0.0; |
| 280 | runtime::AudioBuffer merged_audio; |
| 281 | for (const auto & chunk_request : chunk_requests) { |
| 282 | const auto generator_start = Clock::now(); |
| 283 | const auto generated = generator_->generate( |
| 284 | chunk_request.text_input->text, prompt, generation_options); |
| 285 | generator_ms += engine::debug::elapsed_ms(generator_start, Clock::now()); |
| 286 | |
| 287 | const auto decoder_start = Clock::now(); |
| 288 | auto audio = decoder_->decode_features(generated.decode_features, |
| 289 | generated.decode_patches); |
| 290 | if (generated.decode_trim_patches > 0) { |
| 291 | const int64_t trim_samples = |
| 292 | generated.decode_trim_patches * assets_->config.patch_size * |
| 293 | product(assets_->config.audio_vae.decoder_rates); |
| 294 | if (trim_samples > static_cast<int64_t>(audio.samples.size())) { |
| 295 | throw std::runtime_error( |
| 296 | "VoxCPM2 decoded continuation trim exceeds audio length"); |
| 297 | } |
| 298 | audio.samples.erase( |
| 299 | audio.samples.begin(), |
| 300 | audio.samples.begin() + static_cast<std::ptrdiff_t>(trim_samples)); |
| 301 | } |
| 302 | decoder_ms += engine::debug::elapsed_ms(decoder_start, Clock::now()); |
| 303 | runtime::append_audio_buffer(merged_audio, audio); |
| 304 | } |
| 305 | result.audio_output = std::move(merged_audio); |
| 306 | |
| 307 | const auto wall_end = Clock::now(); |
| 308 | debug::trace_log_scalar("voxcpm2.text_chunk_size", text_chunk_size); |
| 309 | debug::trace_log_scalar("voxcpm2.text_chunk_mode", |
| 310 | engine::text::text_chunk_mode_name(text_chunk_mode)); |
| 311 | debug::trace_log_scalar("voxcpm2.text_chunk_count", |
| 312 | static_cast<int64_t>(chunk_requests.size())); |
| 313 | debug::timing_log_scalar("voxcpm2.generator_ms", generator_ms); |
| 314 | debug::timing_log_scalar("voxcpm2.audiovae_decoder_ms", decoder_ms); |
| 315 | debug::timing_log_scalar("session.wall_ms", |
| 316 | engine::debug::elapsed_ms(wall_start, wall_end)); |
| 317 | return result; |
| 318 | } |
| 319 | |
| 320 | runtime::TaskResult |
| 321 | VoxCPM2SessionBase::run_streaming_request( |
| 322 | const runtime::TaskRequest &request, |
| 323 | const runtime::StreamEventCallback &stream_event_sink) { |
| 324 | require_prepared("VoxCPM2 run_streaming"); |
| 325 | if (task_.mode != runtime::RunMode::Streaming) { |
| 326 | throw std::runtime_error( |
| 327 | "VoxCPM2 run_streaming requires a streaming session"); |
| 328 | } |
no test coverage detected