| 193 | const bool mono_compatible = assets_->config.channels == 2 && request.audio->channels == 1; |
| 194 | if (request.audio->channels != assets_->config.channels && !mono_compatible) { |
| 195 | throw std::runtime_error( |
| 196 | "RoFormer prepare() channel mismatch: expected " + |
| 197 | std::to_string(assets_->config.channels) + ", got " + |
| 198 | std::to_string(request.audio->channels)); |
| 199 | } |
| 200 | mark_prepared(); |
| 201 | } |
| 202 | |
| 203 | runtime::TaskResult RoformerSession::run(const runtime::TaskRequest & request) { |
| 204 | require_prepared("RoFormer run()"); |
| 205 | runtime::validate_spec_backed_request_options(request.options, *contract_, assets_->config.family); |
| 206 | if (!request.audio_input.has_value()) { |
| 207 | throw std::runtime_error("RoFormer run() requires audio_input"); |
| 208 | } |
| 209 | const auto total_start = Clock::now(); |
| 210 | |
| 211 | const auto & config = runtime_->config(); |
| 212 | const std::string log_prefix = config.family + ".session."; |
| 213 | const auto & request_audio = *request.audio_input; |
| 214 | const bool original_mono = config.channels == 2 && request_audio.channels == 1; |
| 215 | if (request_audio.sample_rate != config.sample_rate || |
| 216 | (request_audio.channels != config.channels && !original_mono)) { |
| 217 | throw std::runtime_error("RoFormer run() audio_input does not match prepared audio contract"); |
| 218 | } |
| 219 | engine::debug::trace_log_scalar(log_prefix + "sample_rate", config.sample_rate); |
| 220 | engine::debug::trace_log_scalar(log_prefix + "channels", config.channels); |
| 221 | engine::debug::trace_log_scalar(log_prefix + "chunk_size", chunk_size_); |
| 222 | engine::debug::trace_log_scalar(log_prefix + "step", step_); |
| 223 | engine::debug::trace_log_scalar(log_prefix + "original_mono", original_mono); |
| 224 | |
| 225 | const auto prepare_start = Clock::now(); |
| 226 | const auto audio = original_mono |
| 227 | ? runtime::AudioBuffer{ |
| 228 | request_audio.sample_rate, |
| 229 | config.channels, |
| 230 | engine::audio::duplicate_mono_to_interleaved_channels(request_audio.samples, config.channels)} |
| 231 | : request_audio; |
| 232 | auto planar = engine::audio::deinterleave_to_planar_channels(audio.samples, audio.channels); |
| 233 | int64_t total_length = static_cast<int64_t>(audio.samples.size() / static_cast<size_t>(audio.channels)); |
| 234 | bool padded_borders = false; |
| 235 | if (total_length > 2 * border_ && border_ > 0) { |
| 236 | std::vector<float> padded(static_cast<size_t>(audio.channels * (total_length + 2 * border_)), 0.0f); |
| 237 | const engine::audio::AudioChunkSpec border_spec{ |
| 238 | total_length + 2 * border_, |
| 239 | total_length + 2 * border_, |
| 240 | engine::audio::AudioChunkPadMode::Reflect, |
| 241 | engine::audio::AudioChunkTailAlignment::Start, |
| 242 | 0, |
| 243 | }; |
| 244 | const engine::audio::AudioChunkSpan border_span{ |
| 245 | 0, |
| 246 | 0, |
| 247 | total_length + 2 * border_, |
| 248 | -border_, |
| 249 | 0, |
| 250 | }; |
| 251 | engine::audio::copy_planar_chunk( |
| 252 | padded, |
no test coverage detected