Upgrade rubato
This commit is contained in:
parent
18dccb8a64
commit
3068084b5f
|
|
@ -280,6 +280,43 @@ version = "1.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "audio-core"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f93ebbf82d06013f4c41fe71303feb980cddd78496d904d06be627972de51a24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "audioadapter"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e25c5bb54993ad4693d8b68b6f29f872c5fd9f92a6469d0acb0cbaf80a13d0f9"
|
||||||
|
dependencies = [
|
||||||
|
"audio-core",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "audioadapter-buffers"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6af89882334c4e501faa08992888593ada468f9e1ab211635c32f9ada7786e0"
|
||||||
|
dependencies = [
|
||||||
|
"audioadapter",
|
||||||
|
"audioadapter-sample",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "audioadapter-sample"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e9a3d502fec0b21aa420febe0b110875cf8a7057c49e83a0cace1df6a73e03e"
|
||||||
|
dependencies = [
|
||||||
|
"audio-core",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -1972,6 +2009,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"atoi",
|
"atoi",
|
||||||
"atomic",
|
"atomic",
|
||||||
|
"audioadapter-buffers",
|
||||||
"bitflags 2.10.0",
|
"bitflags 2.10.0",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cc",
|
"cc",
|
||||||
|
|
@ -3530,14 +3568,18 @@ checksum = "ad8388ea1a9e0ea807e442e8263a699e7edcb320ecbcd21b4fa8ff859acce3ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rubato"
|
name = "rubato"
|
||||||
version = "0.16.2"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5258099699851cfd0082aeb645feb9c084d9a5e1f1b8d5372086b989fc5e56a1"
|
checksum = "90173154a8a14e6adb109ea641743bc95ec81c093d94e70c6763565f7108ebeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"audioadapter",
|
||||||
|
"audioadapter-buffers",
|
||||||
"num-complex",
|
"num-complex",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"realfft",
|
"realfft",
|
||||||
|
"visibility",
|
||||||
|
"windowfunctions",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -4543,6 +4585,17 @@ version = "0.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "visibility"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
|
@ -5023,6 +5076,15 @@ dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windowfunctions"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90628d739333b7c5d2ee0b70210b97b8cddc38440c682c96fd9e2c24c2db5f3a"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows"
|
name = "windows"
|
||||||
version = "0.54.0"
|
version = "0.54.0"
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ edition = "2024"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
atoi = "2"
|
atoi = "2"
|
||||||
|
audioadapter-buffers = "2"
|
||||||
atomic = "0.6"
|
atomic = "0.6"
|
||||||
bitflags = { version = "2", features = ["serde"] }
|
bitflags = { version = "2", features = ["serde"] }
|
||||||
bytemuck = { version = "1", features = ["derive"] }
|
bytemuck = { version = "1", features = ["derive"] }
|
||||||
|
|
@ -38,7 +39,7 @@ pollster = "0.4"
|
||||||
rand = "0.9"
|
rand = "0.9"
|
||||||
rfd = "0.17"
|
rfd = "0.17"
|
||||||
rtrb = "0.3"
|
rtrb = "0.3"
|
||||||
rubato = "0.16"
|
rubato = "1"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
thread-priority = "3"
|
thread-priority = "3"
|
||||||
|
|
|
||||||
70
src/audio.rs
70
src/audio.rs
|
|
@ -1,17 +1,17 @@
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{Result, bail};
|
use anyhow::{Result, bail};
|
||||||
|
use audioadapter_buffers::direct::InterleavedSlice;
|
||||||
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
|
||||||
use itertools::Itertools;
|
use rubato::Resampler;
|
||||||
use rubato::{FastFixedOut, Resampler};
|
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
pub struct Audio {
|
pub struct Audio {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
stream: cpal::Stream,
|
stream: cpal::Stream,
|
||||||
sampler: FastFixedOut<f32>,
|
sampler: rubato::Async<f32>,
|
||||||
input_buffer: Vec<Vec<f32>>,
|
input_buffer: Vec<f32>,
|
||||||
output_buffer: Vec<Vec<f32>>,
|
output_buffer: Vec<f32>,
|
||||||
sample_sink: rtrb::Producer<f32>,
|
sample_sink: rtrb::Producer<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,17 +32,18 @@ impl Audio {
|
||||||
let mut config = config.with_max_sample_rate().config();
|
let mut config = config.with_max_sample_rate().config();
|
||||||
let resample_ratio = config.sample_rate.0 as f64 / VB_FREQUENCY as f64;
|
let resample_ratio = config.sample_rate.0 as f64 / VB_FREQUENCY as f64;
|
||||||
let chunk_size = (834.0 * resample_ratio) as usize;
|
let chunk_size = (834.0 * resample_ratio) as usize;
|
||||||
let sampler = FastFixedOut::new(
|
let sampler = rubato::Async::new_poly(
|
||||||
resample_ratio,
|
resample_ratio,
|
||||||
64.0,
|
64.0,
|
||||||
rubato::PolynomialDegree::Cubic,
|
rubato::PolynomialDegree::Cubic,
|
||||||
chunk_size,
|
chunk_size,
|
||||||
2,
|
2,
|
||||||
|
rubato::FixedAsync::Output,
|
||||||
)?;
|
)?;
|
||||||
config.buffer_size = cpal::BufferSize::Fixed(sampler.output_frames_max() as u32);
|
config.buffer_size = cpal::BufferSize::Fixed(sampler.output_frames_max() as u32);
|
||||||
|
|
||||||
let input_buffer = sampler.input_buffer_allocate(true);
|
let input_buffer = Vec::with_capacity(sampler.nbr_channels() * sampler.input_frames_max());
|
||||||
let output_buffer = sampler.output_buffer_allocate(true);
|
let output_buffer = vec![0.0; sampler.nbr_channels() * sampler.output_frames_max()];
|
||||||
let (sample_sink, mut sample_source) =
|
let (sample_sink, mut sample_source) =
|
||||||
rtrb::RingBuffer::new(sampler.output_frames_max() * 4);
|
rtrb::RingBuffer::new(sampler.output_frames_max() * 4);
|
||||||
|
|
||||||
|
|
@ -78,34 +79,37 @@ impl Audio {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, samples: &[f32]) {
|
pub fn update(&mut self, mut samples: &[f32]) {
|
||||||
for sample in samples.chunks_exact(2) {
|
while self.input_buffer.len() + samples.len() >= self.sampler.input_frames_next() * 2 {
|
||||||
for (channel, value) in self.input_buffer.iter_mut().zip(sample) {
|
let samples_needed = (self.sampler.input_frames_next() * 2) - self.input_buffer.len();
|
||||||
channel.push(*value);
|
let (current_samples, future_samples) = samples.split_at(samples_needed);
|
||||||
}
|
self.input_buffer.extend_from_slice(current_samples);
|
||||||
if self.input_buffer[0].len() >= self.sampler.input_frames_next() {
|
samples = future_samples;
|
||||||
let (_, output_samples) = self
|
|
||||||
.sampler
|
let buffer_in =
|
||||||
.process_into_buffer(&self.input_buffer, &mut self.output_buffer, None)
|
InterleavedSlice::new(&self.input_buffer, 2, self.sampler.input_frames_next())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let mut buffer_out = InterleavedSlice::new_mut(
|
||||||
let chunk = match self.sample_sink.write_chunk_uninit(output_samples * 2) {
|
&mut self.output_buffer,
|
||||||
Ok(c) => c,
|
2,
|
||||||
Err(rtrb::chunks::ChunkError::TooFewSlots(n)) => {
|
self.sampler.output_frames_next(),
|
||||||
self.sample_sink.write_chunk_uninit(n).unwrap()
|
)
|
||||||
}
|
.unwrap();
|
||||||
};
|
let (_, output_samples) = self
|
||||||
let interleaved = self.output_buffer[0]
|
.sampler
|
||||||
.iter()
|
.process_into_buffer(&buffer_in, &mut buffer_out, None)
|
||||||
.interleave(self.output_buffer[1].iter())
|
.unwrap();
|
||||||
.cloned();
|
let chunk = match self.sample_sink.write_chunk_uninit(output_samples * 2) {
|
||||||
chunk.fill_from_iter(interleaved);
|
Ok(c) => c,
|
||||||
|
Err(rtrb::chunks::ChunkError::TooFewSlots(n)) => {
|
||||||
for channel in &mut self.input_buffer {
|
self.sample_sink.write_chunk_uninit(n).unwrap()
|
||||||
channel.clear();
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
chunk.fill_from_iter(self.output_buffer[..output_samples * 2].iter().copied());
|
||||||
|
|
||||||
|
self.input_buffer.clear();
|
||||||
}
|
}
|
||||||
|
self.input_buffer.extend_from_slice(samples);
|
||||||
|
|
||||||
while self.sample_sink.slots() < self.sampler.output_frames_max() * 2 {
|
while self.sample_sink.slots() < self.sampler.output_frames_max() * 2 {
|
||||||
std::thread::sleep(Duration::from_micros(500));
|
std::thread::sleep(Duration::from_micros(500));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue