use crate::core::types::*;
use std::marker::PhantomData;
use std::any::TypeId;
use crate::Runtime;
use crate::Builder;
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
fn filter(
audio_in: Input, cutoff: Input, audio_out: UseOutput, z1: UseF32, ) {
let default_silence = vec![0.0; audio_out.len()];
let default_cutoff = vec![0.5; audio_out.len()];
let audio_in = audio_in.unwrap_or(&default_silence);
let cutoff = cutoff.unwrap_or(&default_cutoff);
let z1 = z1;
let a = cutoff[0].min(0.99).max(0.0);
for (i, &sample) in audio_in.iter().enumerate() {
let filtered = sample * a + *z1 * (1.0 - a);
audio_out[i] = filtered;
*z1 = filtered;
}
}
struct Filter {
audio_in: Input,
cutoff: Input,
audio_out: UseOutput,
z1: UseF32,
}
impl Processor for Filter {
fn buffers_count() -> usize { 3 }
fn slot_count() -> usize { 1 }
fn call<E: Clone + Copy>(runtime: &Runtime<E>, handle: ContextHandle) {
let ctx = runtime.get_ctx::<Filter>(handle);
let default_silence = vec![0.0; ctx.buffer_size()];
let default_cutoff = vec![0.5; ctx.buffer_size()];
let mut default_output = vec![0.0; ctx.buffer_size()];
let audio_in = ctx.audio_in().unwrap_or(&default_silence);
let cutoff = ctx.cutoff().unwrap_or(&default_cutoff);
let audio_out = ctx.audio_out().unwrap_or(&mut default_output);
let z1 = ctx.z1();
filter(audio_in, cutoff, audio_out, z1);
}
}
impl Filter {
pub const fn named(name: &'static str) -> ProcessorName<Filter> {
ProcessorName::<Filter> { name, _phantom: PhantomData }
}
}
impl ProcessorName<Filter> {
pub fn audio_in(self) -> PortHandle<Input> {
BufferHandle::new(self.name, 0, TypeId::of::<Filter>())
}
pub fn cutoff(self) -> PortHandle<Input> {
BufferHandle::new(self.name, 1, TypeId::of::<Filter>())
}
pub fn audio_out(self) -> PortHandle<UseOutput> {
BufferHandle::new(self.name, 2, TypeId::of::<Filter>())
}
}
impl<'a, E: Clone + Copy> Context<'a, Filter, E> {
pub fn audio_in(&self) -> Option<&[f32]> {
let buffer_idx = self.handle.buffer_ids_start.0 + 0;
if let Some(buffer_id) = self.runtime.buffer_ids[buffer_idx]{
unsafe {
let buffer_cell = self.runtime.buffers
.get(&buffer_id)
.expect("Buffer not found");
let res = &*buffer_cell.get();
return Some(res)
}
}
None
}
pub fn cutoff(&self) -> Option<&[f32]> {
let buffer_idx = self.handle.buffer_ids_start.0 + 1;
if let Some(buffer_id) = self.runtime.buffer_ids[buffer_idx]{
unsafe {
let buffer_cell = self.runtime.buffers
.get(&buffer_id)
.expect("Buffer not found");
let res = &*buffer_cell.get();
return Some(res)
}
}
None
}
pub fn audio_out(&self) -> Option<&mut [f32]> {
let buffer_idx = self.handle.buffer_ids_start.0 + 2;
if let Some(buffer_id) = self.runtime.buffer_ids[buffer_idx]{
unsafe {
let buffer_cell = self.runtime.buffers
.get(&buffer_id)
.expect("Buffer not found");
let res = &mut *buffer_cell.get();
return Some(res)
}
}
None
}
pub fn z1(&'a self) -> &'a mut f32 {
let slot_idx = self.handle.slot_ids_start + 0;
unsafe {
let slot_cell = &self.runtime.slots[slot_idx];
&mut *slot_cell.get()
}
}
}
fn saw_osc(
audio_out: UseOutput,
phase: UseF32,
) {
let frequency = 440.0;
let sample_rate = 44100.0;
let phase_increment = frequency / sample_rate;
for sample in audio_out.iter_mut() {
*sample = (*phase * 2.0 - 1.0) * 0.1;
*phase += phase_increment;
if *phase >= 1.0 {
*phase -= 1.0;
}
}
}
pub fn test_main() -> Result<(), Box<dyn std::error::Error>> {
let (mut runtime, router) = Builder::<()>::new()
.add_processor::<SawOsc>("saw", saw_component)
.buffer_length(1024)
.build();
let _ = router.route(
SawOsc::named("saw").audio_out(),
output()
);
runtime.tick();
let host = cpal::default_host();
let device = host.default_output_device()
.ok_or("No output device available")?;
let config = device.default_output_config()?;
println!("Using config: {:?}", config);
let stream = match config.sample_format() {
cpal::SampleFormat::F32 => {
device.build_output_stream(
&config.into(),
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
runtime.tick();
runtime.write_to(data);
},
|err| eprintln!("Audio stream error: {}", err),
None,
)?
}
_ => return Err("Unsupported sample format".into()),
};
stream.play()?;
println!("Playing 440Hz sawtooth wave! Press Enter to stop...");
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
Ok(())
}