| 158 | } |
| 159 | |
| 160 | runtime::TaskResult MioCodecSession::run(const runtime::TaskRequest & request) { |
| 161 | const auto wall_start = Clock::now(); |
| 162 | require_prepared("MioCodec run"); |
| 163 | if (!request.audio_input.has_value()) { |
| 164 | throw std::runtime_error("MioCodec run() requires audio_input"); |
| 165 | } |
| 166 | if (!request.voice.has_value() || !request.voice->speaker.has_value() || |
| 167 | !request.voice->speaker->audio.has_value()) { |
| 168 | throw std::runtime_error("MioCodec run() requires voice speaker audio for the global reference"); |
| 169 | } |
| 170 | auto timing_start = Clock::now(); |
| 171 | const auto source_audio = prepare_miocodec_mono_audio(*request.audio_input, assets_->config.sample_rate); |
| 172 | engine::debug::timing_log_scalar("miocodec.audio.source_prepare_ms", engine::debug::elapsed_ms(timing_start)); |
| 173 | timing_start = Clock::now(); |
| 174 | const auto reference_audio = prepare_miocodec_mono_audio(*request.voice->speaker->audio, assets_->config.sample_rate); |
| 175 | engine::debug::timing_log_scalar("miocodec.audio.reference_prepare_ms", engine::debug::elapsed_ms(timing_start)); |
| 176 | timing_start = Clock::now(); |
| 177 | const auto source_ssl = local_ssl_->extract(source_audio); |
| 178 | engine::debug::timing_log_scalar("miocodec.local_ssl_ms", engine::debug::elapsed_ms(timing_start)); |
| 179 | timing_start = Clock::now(); |
| 180 | const auto content = content_encoder_->encode(source_ssl.values, source_ssl.frames); |
| 181 | engine::debug::timing_log_scalar("miocodec.content_encoder_ms", engine::debug::elapsed_ms(timing_start)); |
| 182 | timing_start = Clock::now(); |
| 183 | const auto global = global_reference_->embedding_for_reference(reference_audio); |
| 184 | engine::debug::timing_log_scalar("miocodec.global_reference_ms", engine::debug::elapsed_ms(timing_start)); |
| 185 | const int upsample_factor = std::accumulate( |
| 186 | assets_->config.wave_upsampler_factors.begin(), |
| 187 | assets_->config.wave_upsampler_factors.end(), |
| 188 | 1, |
| 189 | [](int lhs, int rhs) { |
| 190 | return lhs * rhs; |
| 191 | }); |
| 192 | const auto stft_frames = |
| 193 | static_cast<int64_t>(source_audio.size()) / assets_->config.hop_length / upsample_factor; |
| 194 | if (stft_frames <= 0) { |
| 195 | throw std::runtime_error("MioCodec run() audio input is too short for the configured wave decoder"); |
| 196 | } |
| 197 | timing_start = Clock::now(); |
| 198 | const auto head = wave_decoder_->decode(content, global, stft_frames); |
| 199 | engine::debug::timing_log_scalar("miocodec.wave_decoder_ms", engine::debug::elapsed_ms(timing_start)); |
| 200 | if (head.bins != kMioCodecWaveHeadBins) { |
| 201 | throw std::runtime_error("MioCodec wave head bin count mismatch"); |
| 202 | } |
| 203 | const engine::audio::STFTConfig stft_config{ |
| 204 | assets_->config.n_fft, |
| 205 | assets_->config.hop_length, |
| 206 | assets_->config.n_fft, |
| 207 | true, |
| 208 | engine::audio::STFTPadMode::Reflect, |
| 209 | engine::audio::STFTFamily::Kokoro, |
| 210 | }; |
| 211 | timing_start = Clock::now(); |
| 212 | runtime::TaskResult result; |
| 213 | result.audio_output = runtime::AudioBuffer{ |
| 214 | assets_->config.sample_rate, |
| 215 | 1, |
| 216 | waveform_reconstructor_->reconstruct(head, engine::audio::get_cached_stft_window(stft_config)), |
| 217 | }; |
nothing calls this directly
no test coverage detected