tomara-x / quartz

visual programming and dsp playground
https://codeberg.org/tomara-x/quartz
Apache License 2.0
36 stars 2 forks source link

adc #135

Closed tomara-x closed 2 weeks ago

tomara-x commented 3 months ago

input

tomara-x commented 2 weeks ago

why atomics no worky it would've been so easy! (kinda interesting how it's kinda working, but you get clicks of the audio input, not the whole thing)

but at least the stream and reading parts are there.. maybe a snoop will work?

tomara-x commented 2 weeks ago

if you're reading this, give a crossbeam to someone you love today!

so much to do: (in that order cause they depend on each other)

input example

```rust //! process input from mic with fundsp use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; use cpal::{FromSample, SizedSample}; use fundsp::hacker32::*; use crossbeam_channel::{bounded, Receiver, Sender}; #[derive(Clone)] pub struct InputNode { lr: Receiver, rr: Receiver, } impl InputNode { pub fn new(lr: Receiver, rr: Receiver) -> Self { InputNode { lr, rr } } } impl AudioNode for InputNode { const ID: u64 = 1117; type Sample = f32; type Inputs = U0; type Outputs = U2; type Setting = (); #[inline] fn tick( &mut self, _input: &Frame, ) -> Frame { let l = self.lr.recv().unwrap_or(0.); let r = self.rr.recv().unwrap_or(0.); [l, r].into() } } fn main() { // sender / receiver for left and right channels (stereo mic) let (ls, lr) = bounded(64); let (rs, rr) = bounded(64); let host = cpal::default_host(); // input let in_device = host.default_input_device().unwrap(); let in_config = in_device.default_input_config().unwrap(); match in_config.sample_format() { cpal::SampleFormat::F32 => run_in::(&in_device, &in_config.into(), ls, rs), cpal::SampleFormat::I16 => run_in::(&in_device, &in_config.into(), ls, rs), cpal::SampleFormat::U16 => run_in::(&in_device, &in_config.into(), ls, rs), format => eprintln!("unsupported sample format: {}", format), } // output let out_device = host.default_output_device().unwrap(); let out_config = out_device.default_output_config().unwrap(); match out_config.sample_format() { cpal::SampleFormat::F32 => run_out::(&out_device, &out_config.into(), lr, rr), cpal::SampleFormat::I16 => run_out::(&out_device, &out_config.into(), lr, rr), cpal::SampleFormat::U16 => run_out::(&out_device, &out_config.into(), lr, rr), format => eprintln!("unsupported sample format: {}", format), } std::thread::sleep(std::time::Duration::from_secs(100)); } fn run_in( device: &cpal::Device, config: &cpal::StreamConfig, ls: Sender, rs: Sender, ) where T: SizedSample, f32: FromSample { let channels = config.channels as usize; let err_fn = |err| eprintln!("an error occurred on stream: {}", err); let stream = device.build_input_stream( config, move |data: &[T], _: &cpal::InputCallbackInfo| { read_data(data, channels, ls.clone(), rs.clone()) }, err_fn, None, ); if let Ok(stream) = stream { if let Ok(()) = stream.play() { std::mem::forget(stream); } } } fn read_data(input: &[T], channels: usize, ls: Sender, rs: Sender) where T: SizedSample, f32: FromSample { for frame in input.chunks(channels) { for (channel, sample) in frame.iter().enumerate() { if channel & 1 == 0 { let _ = ls.send(sample.to_sample::()); } else { let _ = rs.send(sample.to_sample::()); } } } } fn run_out( device: &cpal::Device, config: &cpal::StreamConfig, lr: Receiver, rr: Receiver, ) where T: SizedSample + FromSample, { let channels = config.channels as usize; let input = An(InputNode::new(lr, rr)); let reverb = reverb_stereo(40., 5., 1.); let chorus = chorus(0, 0.015, 0.005, 0.5) | chorus(0, 0.015, 0.005, 0.5); let graph = input >> chorus >> reverb; let mut graph = BlockRateAdapter32::new(Box::new(graph)); graph.set_sample_rate(config.sample_rate.0 as f64); let mut next_value = move || graph.get_stereo(); let err_fn = |err| eprintln!("an error occurred on stream: {}", err); let stream = device.build_output_stream( config, move |data: &mut [T], _: &cpal::OutputCallbackInfo| { write_data(data, channels, &mut next_value) }, err_fn, None, ); if let Ok(stream) = stream { if let Ok(()) = stream.play() { std::mem::forget(stream); } } } fn write_data(output: &mut [T], channels: usize, next_sample: &mut dyn FnMut() -> (f32, f32)) where T: SizedSample + FromSample, { for frame in output.chunks_mut(channels) { let sample = next_sample(); let left = T::from_sample(sample.0); let right = T::from_sample(sample.1); for (channel, sample) in frame.iter_mut().enumerate() { if channel & 1 == 0 { *sample = left; } else { *sample = right; } } } } ```

better 8fe8611

tomara-x commented 2 weeks ago

[james earl jones voice] totes mcgoats