mirror of
https://github.com/mii443/maudio-router.git
synced 2025-08-22 16:05:35 +00:00
67 lines
2.2 KiB
Rust
67 lines
2.2 KiB
Rust
use rubato::{Resampler, SincFixedIn, SincInterpolationParameters, SincInterpolationType, WindowFunction};
|
|
|
|
const MAX_CHUNK_SIZE: usize = 1024;
|
|
|
|
pub fn resampling(
|
|
current_sample_rate: u32,
|
|
target_sample_rate: u32,
|
|
data: Vec<Vec<f32>>,
|
|
) -> Result<Vec<Vec<f32>>, Box<dyn std::error::Error>> {
|
|
let channels = data.len();
|
|
let samples = data[0].len();
|
|
|
|
let resample_ratio = target_sample_rate as f64 / current_sample_rate as f64;
|
|
|
|
let params = SincInterpolationParameters {
|
|
sinc_len: 256,
|
|
f_cutoff: 0.95,
|
|
interpolation: SincInterpolationType::Linear,
|
|
oversampling_factor: 256,
|
|
window: WindowFunction::BlackmanHarris2,
|
|
};
|
|
|
|
let mut output = vec![Vec::new(); channels];
|
|
let expected_output_len = (samples as f64 * resample_ratio).round() as usize;
|
|
|
|
for chunk_start in (0..samples).step_by(MAX_CHUNK_SIZE) {
|
|
let chunk_end = (chunk_start + MAX_CHUNK_SIZE).min(samples);
|
|
let chunk_size = chunk_end - chunk_start;
|
|
|
|
let mut resampler = SincFixedIn::<f32>::new(
|
|
resample_ratio,
|
|
2.0,
|
|
SincInterpolationParameters {
|
|
sinc_len: 256,
|
|
f_cutoff: 0.95,
|
|
interpolation: SincInterpolationType::Linear,
|
|
oversampling_factor: 256,
|
|
window: WindowFunction::BlackmanHarris2,
|
|
},
|
|
chunk_size,
|
|
channels,
|
|
)?;
|
|
|
|
let mut input: Vec<&[f32]> = data
|
|
.iter()
|
|
.map(|channel| &channel[chunk_start..chunk_end])
|
|
.collect();
|
|
|
|
let mut chunk_output = vec![vec![0.0; resampler.output_frames_next()]; channels];
|
|
let mut output_buffers: Vec<&mut [f32]> = chunk_output
|
|
.iter_mut()
|
|
.map(|channel| channel.as_mut_slice())
|
|
.collect();
|
|
|
|
let (_, output_frames) = resampler.process_into_buffer(&input, &mut output_buffers, None)?;
|
|
|
|
for (channel_output, chunk_channel_output) in output.iter_mut().zip(chunk_output.iter()) {
|
|
channel_output.extend_from_slice(&chunk_channel_output[..output_frames]);
|
|
}
|
|
}
|
|
|
|
for channel in output.iter_mut() {
|
|
channel.truncate(expected_output_len);
|
|
}
|
|
|
|
Ok(output)
|
|
} |