// Symphonia // Copyright (c) 2019-2022 The Project Symphonia Developers. // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. use symphonia::core::audio::{AudioBuffer, AudioBufferRef, Signal, SignalSpec}; use symphonia::core::conv::{FromSample, IntoSample}; use symphonia::core::sample::Sample; pub struct Resampler { resampler: rubato::FftFixedIn, input: Vec>, output: Vec>, interleaved: Vec, duration: usize, } impl Resampler where T: Sample + FromSample + IntoSample, { fn resample_inner(&mut self) -> &[T] { { //let mut input = heapless::Vec::::new(); let mut input: arrayvec::ArrayVec<&[f32], 32> = Default::default(); for channel in self.input.iter() { input.push(&channel[..self.duration]); } // Resample. rubato::Resampler::process_into_buffer( &mut self.resampler, &input, &mut self.output, None, ) .unwrap(); } // Remove consumed samples from the input buffer. for channel in self.input.iter_mut() { channel.drain(0..self.duration); } // Interleave the planar samples from Rubato. let num_channels = self.output.len(); self.interleaved.resize(num_channels * self.output[0].len(), T::MID); for (i, frame) in self.interleaved.chunks_exact_mut(num_channels).enumerate() { for (ch, s) in frame.iter_mut().enumerate() { *s = self.output[ch][i].into_sample(); } } &self.interleaved } } impl Resampler where T: Sample + FromSample + IntoSample, { pub fn new(spec: SignalSpec, to_sample_rate: usize, duration: u64) -> Self { let duration = duration as usize; let num_channels = spec.channels.count(); let resampler = rubato::FftFixedIn::::new( spec.rate as usize, to_sample_rate, duration, 2, num_channels, ) .unwrap(); let output = rubato::Resampler::output_buffer_allocate(&resampler); let input = vec![Vec::with_capacity(duration); num_channels]; Self { resampler, input, output, duration, interleaved: Default::default() } } /// Resamples a planar/non-interleaved input. /// /// Returns the resampled samples in an interleaved format. pub fn resample(&mut self, input: AudioBufferRef<'_>) -> Option<&[T]> { // Copy and convert samples into input buffer. convert_samples_any(&input, &mut self.input); // Check if more samples are required. if self.input[0].len() < self.duration { return None; } Some(self.resample_inner()) } /// Resample any remaining samples in the resample buffer. pub fn flush(&mut self) -> Option<&[T]> { let len = self.input[0].len(); if len == 0 { return None; } let partial_len = len % self.duration; if partial_len != 0 { // Fill each input channel buffer with silence to the next multiple of the resampler // duration. for channel in self.input.iter_mut() { channel.resize(len + (self.duration - partial_len), f32::MID); } } Some(self.resample_inner()) } } fn convert_samples_any(input: &AudioBufferRef<'_>, output: &mut [Vec]) { match input { AudioBufferRef::U8(input) => convert_samples(input, output), AudioBufferRef::U16(input) => convert_samples(input, output), AudioBufferRef::U24(input) => convert_samples(input, output), AudioBufferRef::U32(input) => convert_samples(input, output), AudioBufferRef::S8(input) => convert_samples(input, output), AudioBufferRef::S16(input) => convert_samples(input, output), AudioBufferRef::S24(input) => convert_samples(input, output), AudioBufferRef::S32(input) => convert_samples(input, output), AudioBufferRef::F32(input) => convert_samples(input, output), AudioBufferRef::F64(input) => convert_samples(input, output), } } fn convert_samples(input: &AudioBuffer, output: &mut [Vec]) where S: Sample + IntoSample, { for (c, dst) in output.iter_mut().enumerate() { let src = input.chan(c); dst.extend(src.iter().map(|&s| s.into_sample())); } }