| 288 | } // namespace |
| 289 | |
| 290 | std::optional<std::vector<float>> try_resample_mono_soxr( |
| 291 | const std::vector<float> & mono_samples, |
| 292 | int source_sample_rate_hz, |
| 293 | int target_sample_rate_hz, |
| 294 | const SoxrResampleOptions & options) { |
| 295 | if (source_sample_rate_hz <= 0 || target_sample_rate_hz <= 0) { |
| 296 | throw std::runtime_error("soxr resampling requires positive sample rates"); |
| 297 | } |
| 298 | if (source_sample_rate_hz == target_sample_rate_hz || mono_samples.empty()) { |
| 299 | return mono_samples; |
| 300 | } |
| 301 | const SoxrApi & soxr = get_soxr_api(); |
| 302 | if (!soxr.available()) { |
| 303 | log_soxr_fallback(options, "library was not found"); |
| 304 | return std::nullopt; |
| 305 | } |
| 306 | if (!soxr.supports_profile(options.profile)) { |
| 307 | log_soxr_fallback(options, "required symbols were not resolved"); |
| 308 | return std::nullopt; |
| 309 | } |
| 310 | |
| 311 | const size_t expected = expected_resample_output_count( |
| 312 | mono_samples.size(), |
| 313 | source_sample_rate_hz, |
| 314 | target_sample_rate_hz); |
| 315 | std::vector<float> output(expected + options.output_padding, 0.0F); |
| 316 | size_t input_done = 0; |
| 317 | size_t output_done = 0; |
| 318 | constexpr unsigned long kSoxrHq = 4; |
| 319 | auto quality_spec = soxr.quality_spec()(kSoxrHq, 0); |
| 320 | SoxrIoSpec io_spec; |
| 321 | SoxrRuntimeSpec runtime_spec; |
| 322 | const SoxrIoSpec * io_spec_ptr = nullptr; |
| 323 | const SoxrRuntimeSpec * runtime_spec_ptr = nullptr; |
| 324 | if (options.profile == SoxrResampleProfile::ExplicitFloat32Runtime) { |
| 325 | io_spec = soxr.io_spec()(kSoxrFloat32Interleaved, kSoxrFloat32Interleaved); |
| 326 | runtime_spec = soxr.runtime_spec()(1); |
| 327 | io_spec_ptr = &io_spec; |
| 328 | runtime_spec_ptr = &runtime_spec; |
| 329 | } |
| 330 | const SoxrApi::SoxrError error = soxr.oneshot()( |
| 331 | static_cast<double>(source_sample_rate_hz), |
| 332 | static_cast<double>(target_sample_rate_hz), |
| 333 | 1, |
| 334 | mono_samples.data(), |
| 335 | mono_samples.size(), |
| 336 | &input_done, |
| 337 | output.data(), |
| 338 | output.size(), |
| 339 | &output_done, |
| 340 | io_spec_ptr, |
| 341 | &quality_spec, |
| 342 | runtime_spec_ptr); |
| 343 | if (error != nullptr) { |
| 344 | log_soxr_fallback(options, error); |
| 345 | return std::nullopt; |
| 346 | } |
| 347 | if (options.require_full_input && input_done != mono_samples.size()) { |
no test coverage detected