Add allocator and switch to tokio bounded channels instead of thingbuf

This commit is contained in:
2025-06-03 23:17:40 +02:00
parent 880046c1ce
commit a450e81338
6 changed files with 442 additions and 18 deletions

26
src/allocator.rs Normal file
View File

@@ -0,0 +1,26 @@
use std::sync::Arc;
use crate::AudioChunk;
pub struct Allocator {
buffer_size: usize,
allocated_buffer_sender: tokio::sync::mpsc::Sender<Arc<AudioChunk>>,
}
impl Allocator {
pub fn new(buffer_size: usize, allocated_buffer_sender: tokio::sync::mpsc::Sender<Arc<AudioChunk>>) -> Self {
while allocated_buffer_sender.try_send(AudioChunk::allocate(buffer_size)).is_ok() {}
Self {
buffer_size,
allocated_buffer_sender,
}
}
pub async fn run(self) {
loop {
let chunk = AudioChunk::allocate(self.buffer_size);
if self.allocated_buffer_sender.send(chunk).await.is_err() {
break;
}
}
}
}

View File

@@ -53,9 +53,9 @@ impl AudioChunk {
/// Write samples into this chunk and additional chunks as needed.
/// Uses the factory to get pre-allocated chunks when current chunk fills up.
pub fn write_samples<F>(this: &mut Arc<Self>, samples: &[f32], chunk_factory: F) -> Result<(), LooperError>
pub fn write_samples<F>(this: &mut Arc<Self>, samples: &[f32], mut chunk_factory: F) -> Result<(), LooperError>
where
F: Fn() -> Result<Arc<AudioChunk>, LooperError>
F: FnMut() -> Result<Arc<AudioChunk>, LooperError>
{
let sample_count = samples.len();

View File

@@ -1,21 +1,30 @@
mod audio_chunk;
mod looper_error;
mod allocator;
use audio_chunk::AudioChunk;
use looper_error::LooperError;
use allocator::Allocator;
fn main() {
let mut chunk = AudioChunk::allocate(2);
use std::cell::RefCell;
let available_chunks = RefCell::new(vec![
AudioChunk::allocate(2),
AudioChunk::allocate(2),
]);
let factory = || available_chunks.borrow_mut().pop().ok_or(LooperError::ChunkAllocation);
let samples = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; // 6 samples, each chunk holds 2
AudioChunk::write_samples(&mut chunk, &samples, factory).unwrap();
AudioChunk::consolidate(&chunk);
println!("Audio chunk allocated with size: {}", chunk.samples.len());
let (allocated_buffer_sender, mut allocated_buffer_receiver) = tokio::sync::mpsc::channel(1);
let allocator = Allocator::new(3, allocated_buffer_sender);
let mut factory = move || {
match allocated_buffer_receiver.try_recv() {
Ok(chunk) => Ok(chunk),
Err(_) => Err(LooperError::ChunkAllocation),
}
};
let handle = std::thread::spawn(move || {
let mut chunk = factory().unwrap();
std::thread::sleep(std::time::Duration::from_millis(100));
let samples = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; // 6 samples, each chunk holds 2
AudioChunk::write_samples(&mut chunk, &samples, factory).unwrap();
AudioChunk::consolidate(&chunk);
});
let tokio_runtime = tokio::runtime::Builder::new_current_thread().build().unwrap();
tokio_runtime.block_on(allocator.run());
handle.join().unwrap();
}