This commit is contained in:
mii443
2024-09-04 16:11:11 +09:00
parent b63d379488
commit cb7579d71e
4 changed files with 386 additions and 457 deletions

742
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
virtual_devices: virtual_devices:
- name: "mic" - name: "mic"
channels: 2 channels: 2
sample_rate: 96000 sample_rate: 48000
routes: routes:
input: input:
- name: "Mic" - name: "Mic"
virtual_device: "mic" virtual_device: "mic"
device: device:
local: local:
name: "VoiceMeeter Aux Output (VB-Audio VoiceMeeter AUX VAIO)" name: "Voicemeeter Out B2 (VB-Audio Voicemeeter VAIO)"
output: output:
- name: "Speaker" - name: "Speaker"
input: input:

View File

@ -1,49 +1,67 @@
use num::Complex; use rubato::{Resampler, SincFixedIn, SincInterpolationParameters, SincInterpolationType, WindowFunction};
use rustfft::FftPlanner;
const MAX_CHUNK_SIZE: usize = 1024;
#[inline]
pub fn resampling( pub fn resampling(
current_sample_rate: u32, current_sample_rate: u32,
target_sample_rate: u32, target_sample_rate: u32,
data: Vec<Vec<f32>>, data: Vec<Vec<f32>>,
) -> Vec<Vec<f32>> { ) -> Result<Vec<Vec<f32>>, Box<dyn std::error::Error>> {
let mut resampled_data = Vec::new(); let channels = data.len();
let samples = data[0].len();
let mut planner = FftPlanner::new(); let resample_ratio = target_sample_rate as f64 / current_sample_rate as f64;
for channel_data in data { let params = SincInterpolationParameters {
let mut complex_data: Vec<Complex<f32>> = sinc_len: 256,
channel_data.iter().map(|&x| Complex::new(x, 0.0)).collect(); f_cutoff: 0.95,
interpolation: SincInterpolationType::Linear,
oversampling_factor: 256,
window: WindowFunction::BlackmanHarris2,
};
let fft = planner.plan_fft_forward(complex_data.len()); let mut output = vec![Vec::new(); channels];
fft.process(&mut complex_data); let expected_output_len = (samples as f64 * resample_ratio).round() as usize;
let adjustment_factor = target_sample_rate as f64 / current_sample_rate as f64; for chunk_start in (0..samples).step_by(MAX_CHUNK_SIZE) {
let new_size = (complex_data.len() as f64 * adjustment_factor).round() as usize; let chunk_end = (chunk_start + MAX_CHUNK_SIZE).min(samples);
let mut adjusted_complex_data; let chunk_size = chunk_end - chunk_start;
if adjustment_factor == 1.0 { let mut resampler = SincFixedIn::<f32>::new(
adjusted_complex_data = complex_data; resample_ratio,
} else if adjustment_factor > 1.0 { 2.0,
adjusted_complex_data = complex_data.into_iter().collect(); SincInterpolationParameters {
adjusted_complex_data.resize(new_size, Complex::new(0.0, 0.0)); sinc_len: 256,
} else { f_cutoff: 0.95,
adjusted_complex_data = complex_data.into_iter().collect(); interpolation: SincInterpolationType::Linear,
adjusted_complex_data.resize(new_size, Complex::new(0.0, 0.0)); oversampling_factor: 256,
} window: WindowFunction::BlackmanHarris2,
},
chunk_size,
channels,
)?;
let ifft = planner.plan_fft_inverse(adjusted_complex_data.len()); let mut input: Vec<&[f32]> = data
ifft.process(&mut adjusted_complex_data); .iter()
.map(|channel| &channel[chunk_start..chunk_end])
let len = adjusted_complex_data.len();
let resampled_channel: Vec<f32> = adjusted_complex_data
.into_iter()
.map(|x| x.re / len as f32)
.collect(); .collect();
resampled_data.push(resampled_channel); 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]);
}
} }
resampled_data for channel in output.iter_mut() {
channel.truncate(expected_output_len);
}
Ok(output)
} }

View File

@ -89,7 +89,14 @@ impl VirtualDevice {
pub fn write_input_multiple_channels(&mut self, input_buffer: &[Vec<f32>]) { pub fn write_input_multiple_channels(&mut self, input_buffer: &[Vec<f32>]) {
for (sample_rate, buffer) in self.output_buffer.iter_mut() { for (sample_rate, buffer) in self.output_buffer.iter_mut() {
let buffer_resample = resampling(self.sample_rate, *sample_rate, input_buffer.to_vec()); let buffer_resample = if self.sample_rate == *sample_rate {
input_buffer.to_vec()
} else {
resampling(self.sample_rate, *sample_rate, input_buffer.to_vec()).unwrap()
};
println!("Resampling: {} -> {}", input_buffer[0].len(), buffer_resample[0].len());
(0..self.channels as usize).for_each(|i| buffer[i].extend(buffer_resample[i].iter())); (0..self.channels as usize).for_each(|i| buffer[i].extend(buffer_resample[i].iter()));
} }
} }