| 206 | const engine::audio::AudioChunkSpec chunk_spec{ |
| 207 | chunk_size_, |
| 208 | step_, |
| 209 | engine::audio::AudioChunkPadMode::Zero, |
| 210 | engine::audio::AudioChunkTailAlignment::Center, |
| 211 | 0, |
| 212 | }; |
| 213 | std::vector<float> merge_window(static_cast<size_t>(chunk_size_), 0.0F); |
| 214 | for (const auto & chunk : engine::audio::plan_audio_chunks(total_frames, chunk_spec)) { |
| 215 | const auto copy_start = std::chrono::steady_clock::now(); |
| 216 | engine::audio::copy_interleaved_chunk_to_planar( |
| 217 | chunk_planar_work_, |
| 218 | audio.samples, |
| 219 | audio.channels, |
| 220 | total_frames, |
| 221 | chunk, |
| 222 | chunk_spec); |
| 223 | const auto copy_end = std::chrono::steady_clock::now(); |
| 224 | chunk_copy_ms += debug::elapsed_ms(copy_start, copy_end); |
| 225 | const auto & chunk_sources = pipeline_->separate_chunk(chunk_planar_work_); |
| 226 | const auto & timing = pipeline_->last_timing(); |
| 227 | frontend_ms += timing.frontend_ms; |
| 228 | graph_ms += timing.graph_ms; |
| 229 | postprocess_ms += timing.postprocess_ms; |
| 230 | graph_rebuild_ms += timing.graph_rebuild_ms; |
| 231 | const int64_t trim_offset = chunk.valid_start_in_chunk; |
| 232 | const auto merge_start = std::chrono::steady_clock::now(); |
| 233 | std::fill(merge_window.begin(), merge_window.end(), 0.0F); |
| 234 | for (int64_t i = 0; i < chunk.valid_samples; ++i) { |
| 235 | merge_window[static_cast<size_t>(trim_offset + i)] = chunk_window_[static_cast<size_t>(i)]; |
| 236 | } |
| 237 | engine::audio::overlap_add_planar_chunk( |
| 238 | result_work_, |
| 239 | counter_work_, |
| 240 | chunk_sources, |
| 241 | num_sources * audio.channels, |
| 242 | total_frames, |
| 243 | chunk, |
| 244 | merge_window, |
| 245 | engine::audio::AudioChunkCounterMode::SharedAcrossLanes); |
| 246 | merge_ms += debug::elapsed_ms(merge_start); |
| 247 | } |
| 248 | |
| 249 | runtime::TaskResult result; |
| 250 | for (int source = 0; source < num_sources; ++source) { |
| 251 | runtime::NamedAudioBuffer named; |
| 252 | named.id = config.sources[static_cast<size_t>(source)]; |
| 253 | named.audio.sample_rate = audio.sample_rate; |
| 254 | named.audio.channels = original_mono ? 1 : audio.channels; |
| 255 | if (original_mono) { |
| 256 | named.audio.samples.resize(static_cast<size_t>(total_frames)); |
| 257 | for (int64_t i = 0; i < total_frames; ++i) { |
| 258 | const float denom = counter_work_[static_cast<size_t>(i)] > 1.0e-8f |
| 259 | ? counter_work_[static_cast<size_t>(i)] |
| 260 | : 1.0f; |
| 261 | const float * src = result_work_.data() + static_cast<size_t>((source * audio.channels) * total_frames); |
| 262 | named.audio.samples[static_cast<size_t>(i)] = src[i] / denom * global_std + global_mean; |
| 263 | } |
| 264 | } else { |
| 265 | named.audio.samples.resize(static_cast<size_t>(audio.channels * total_frames)); |
nothing calls this directly
no test coverage detected