fix resampling

This commit is contained in:
mii443
2024-09-17 19:19:40 +09:00
parent cb7579d71e
commit 211c145c4c
4 changed files with 61 additions and 23 deletions

16
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug",
"program": "${workspaceFolder}/<executable file>",
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

View File

@ -1,4 +1,4 @@
use rubato::{Resampler, SincFixedIn, SincInterpolationParameters, SincInterpolationType, WindowFunction}; use rubato::{FastFixedIn, FastFixedOut, PolynomialDegree, Resampler, SincFixedIn, SincInterpolationParameters, SincInterpolationType, WindowFunction};
const MAX_CHUNK_SIZE: usize = 1024; const MAX_CHUNK_SIZE: usize = 1024;
@ -65,3 +65,18 @@ pub fn resampling(
Ok(output) Ok(output)
} }
pub fn get_resampler<T>(from: f64, to: f64, channels: usize, chunk_size: usize) -> FastFixedIn<T>
where
T: rubato::Sample
{
let resample_ratio = to / from;
FastFixedIn::<T>::new(
resample_ratio,
2.0,
PolynomialDegree::Cubic,
chunk_size,
channels
).unwrap()
}

View File

@ -1,13 +1,12 @@
use std::{ use std::{
cmp::min, cmp::min, io::Read, mem::MaybeUninit, sync::{Arc, Mutex}
io::Read,
sync::{Arc, Mutex},
}; };
use cpal::{ use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait}, traits::{DeviceTrait, HostTrait, StreamTrait},
Device, Stream, StreamConfig, SupportedStreamConfig, Device, Stream, StreamConfig, SupportedStreamConfig,
}; };
use rubato::FastFixedIn;
use crate::{args::Run, device::virtual_device::VirtualDevice}; use crate::{args::Run, device::virtual_device::VirtualDevice};
@ -351,7 +350,7 @@ fn input_callback<T>(data: &[T], channels: usize, virtual_device: Arc<Mutex<Virt
where where
T: Clone + num::cast::ToPrimitive, T: Clone + num::cast::ToPrimitive,
{ {
let data: Vec<f32> = data.iter().map(|d| d.to_f32().unwrap()).collect(); let data: Vec<f64> = data.iter().map(|d| d.to_f64().unwrap()).collect();
let audio_data = reshape_audio_data(&data, channels); let audio_data = reshape_audio_data(&data, channels);
virtual_device virtual_device
.lock() .lock()
@ -377,7 +376,7 @@ fn output_callback<T>(
data.len() / channels, data.len() / channels,
); );
let mut count = 0; let mut count = 0;
while audio_data.is_none() && count < 1 { while audio_data.is_none() && count < 1000 {
audio_data = virtual_device.take_output( audio_data = virtual_device.take_output(
index, index,
min(channels as u8, vd_channels), min(channels as u8, vd_channels),
@ -401,7 +400,7 @@ fn output_callback<T>(
let audio_data: Vec<T> = audio_data let audio_data: Vec<T> = audio_data
.iter() .iter()
.map(|d| T::from_f32(*d).unwrap()) .map(|d| T::from_f64(*d).unwrap())
.collect(); .collect();
data.clone_from_slice(&audio_data); data.clone_from_slice(&audio_data);

View File

@ -1,6 +1,8 @@
use std::collections::HashMap; use std::{collections::HashMap, mem::MaybeUninit, sync::{Arc, Mutex}};
use crate::audio::resampling::resampling; use rubato::{FastFixedIn, Resampler};
use crate::audio::resampling::{get_resampler, resampling};
pub struct VirtualDevice { pub struct VirtualDevice {
pub name: String, pub name: String,
@ -8,7 +10,7 @@ pub struct VirtualDevice {
pub sample_rate: u32, pub sample_rate: u32,
output_index: HashMap<u32, Vec<usize>>, output_index: HashMap<u32, Vec<usize>>,
output_buffer: HashMap<u32, Vec<Vec<f32>>>, output_buffer: HashMap<u32, (Vec<Vec<f64>>, Arc<Mutex<Option<FastFixedIn<f64>>>>)>,
} }
impl VirtualDevice { impl VirtualDevice {
@ -31,7 +33,7 @@ impl VirtualDevice {
if let std::collections::hash_map::Entry::Vacant(e) = self.output_index.entry(sample_rate) { if let std::collections::hash_map::Entry::Vacant(e) = self.output_index.entry(sample_rate) {
e.insert(Vec::new()); e.insert(Vec::new());
self.output_buffer self.output_buffer
.insert(sample_rate, vec![vec![]; self.channels as usize]); .insert(sample_rate, (vec![vec![]; self.channels as usize], Arc::new(Mutex::new(None))));
} }
let min_index = self.get_min_index(sample_rate); let min_index = self.get_min_index(sample_rate);
self.output_index self.output_index
@ -47,17 +49,17 @@ impl VirtualDevice {
channels: u8, channels: u8,
sample_rate: u32, sample_rate: u32,
take_size: usize, take_size: usize,
) -> Option<Vec<Vec<f32>>> { ) -> Option<Vec<Vec<f64>>> {
let mut buffer = vec![Vec::with_capacity(take_size); channels as usize]; let mut buffer = vec![Vec::with_capacity(take_size); channels as usize];
let start = self.output_index[&sample_rate][index]; let start = self.output_index[&sample_rate][index];
let end = start + take_size; let end = start + take_size;
for channel in 0..channels { for channel in 0..channels {
if end >= self.output_buffer[&sample_rate][channel as usize].len() { if end >= self.output_buffer[&sample_rate].0[channel as usize].len() {
println!( println!(
"End of buffer: {}, {}[{}]", "End of buffer: {}, {}[{}]",
end, end,
self.output_buffer[&sample_rate][channel as usize].len(), self.output_buffer[&sample_rate].0[channel as usize].len(),
channel as usize channel as usize
); );
return None; return None;
@ -67,7 +69,7 @@ impl VirtualDevice {
for i in start..end { for i in start..end {
for channel in 0..channels { for channel in 0..channels {
buffer[channel as usize] buffer[channel as usize]
.push(self.output_buffer[&sample_rate][channel as usize][i]); .push(self.output_buffer[&sample_rate].0[channel as usize][i]);
} }
} }
self.output_index.get_mut(&sample_rate).unwrap()[index] = end; self.output_index.get_mut(&sample_rate).unwrap()[index] = end;
@ -75,8 +77,8 @@ impl VirtualDevice {
let min = self.get_min_index(sample_rate); let min = self.get_min_index(sample_rate);
if min != 0 { if min != 0 {
for i in 0..self.channels as usize { for i in 0..self.channels as usize {
let len = self.output_buffer[&sample_rate][i].len(); let len = self.output_buffer[&sample_rate].0[i].len();
self.output_buffer.get_mut(&sample_rate).unwrap()[i] self.output_buffer.get_mut(&sample_rate).unwrap().0[i]
.drain(0..(if len < min { len } else { min })); .drain(0..(if len < min { len } else { min }));
} }
for i in 0..self.output_index.len() { for i in 0..self.output_index.len() {
@ -87,17 +89,23 @@ impl VirtualDevice {
Some(buffer) Some(buffer)
} }
pub fn write_input_multiple_channels(&mut self, input_buffer: &[Vec<f32>]) { pub fn write_input_multiple_channels(&mut self, input_buffer: &[Vec<f64>]) {
for (sample_rate, buffer) in self.output_buffer.iter_mut() { for (sample_rate, buffer) in self.output_buffer.iter_mut() {
let mut guard = buffer.1.lock().unwrap();
let resampler = {
if guard.is_none() {
*guard = Some(get_resampler::<f64>(self.sample_rate as f64, *sample_rate as f64, self.channels as usize, input_buffer[0].len()));
}
guard.as_mut().unwrap()
};
let buffer_resample = if self.sample_rate == *sample_rate { let buffer_resample = if self.sample_rate == *sample_rate {
input_buffer.to_vec() input_buffer.to_vec()
} else { } else {
resampling(self.sample_rate, *sample_rate, input_buffer.to_vec()).unwrap() resampler.process(input_buffer, None).unwrap()
}; };
println!("Resampling: {} -> {}", input_buffer[0].len(), buffer_resample[0].len()); (0..self.channels as usize).for_each(|i| buffer.0[i].extend(buffer_resample[i].iter()));
(0..self.channels as usize).for_each(|i| buffer[i].extend(buffer_resample[i].iter()));
} }
} }
} }