Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adc #135

Closed
tomara-x opened this issue Mar 29, 2024 · 3 comments
Closed

adc #135

tomara-x opened this issue Mar 29, 2024 · 3 comments

Comments

@tomara-x
Copy link
Owner

input

@tomara-x tomara-x added the maybe label Mar 30, 2024
@tomara-x tomara-x removed the maybe label Jun 7, 2024
@tomara-x
Copy link
Owner Author

tomara-x commented Jun 8, 2024

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 added a commit that referenced this issue Jun 8, 2024
@tomara-x
Copy link
Owner Author

tomara-x commented Jun 8, 2024

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)

  • add set_in_device done
  • bounded channels to 64.. is that gonna be okay? or would that interfere with different buffer sizes? (test) [edit: we seem are okazay]
  • should reset/set_sr on the in node do anything?
  • minimal example in fundsp? [edit: i'm messing something up and it's stuttery]
    • i don't know what i'm doing wrong! i quartz i run it though multiple reverbs and it works just fine. in the standalone fundsp example the reverb makes it underrun. i replace the reverb with some other effect like a delay or chorus and it works.. wait i'm running it in debug.. facepalm
input example

//! 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<f32>,
    rr: Receiver<f32>,
}

impl InputNode {
    pub fn new(lr: Receiver<f32>, rr: Receiver<f32>) -> 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<Self::Sample, Self::Inputs>,
    ) -> Frame<Self::Sample, Self::Outputs> {
        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::<f32>(&in_device, &in_config.into(), ls, rs),
        cpal::SampleFormat::I16 => run_in::<i16>(&in_device, &in_config.into(), ls, rs),
        cpal::SampleFormat::U16 => run_in::<u16>(&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::<f32>(&out_device, &out_config.into(), lr, rr),
        cpal::SampleFormat::I16 => run_out::<i16>(&out_device, &out_config.into(), lr, rr),
        cpal::SampleFormat::U16 => run_out::<u16>(&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<T>(
    device: &cpal::Device,
    config: &cpal::StreamConfig,
    ls: Sender<f32>,
    rs: Sender<f32>,
) where
    T: SizedSample, f32: FromSample<T>
{
    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<T>(input: &[T], channels: usize, ls: Sender<f32>, rs: Sender<f32>)
where
    T: SizedSample, f32: FromSample<T>
{
    for frame in input.chunks(channels) {
        for (channel, sample) in frame.iter().enumerate() {
            if channel & 1 == 0 {
                let _ = ls.send(sample.to_sample::<f32>());
            } else {
                let _ = rs.send(sample.to_sample::<f32>());
            }
        }
    }
}


fn run_out<T>(
    device: &cpal::Device,
    config: &cpal::StreamConfig,
    lr: Receiver<f32>,
    rr: Receiver<f32>,
) where
    T: SizedSample + FromSample<f32>,
{
    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<T>(output: &mut [T], channels: usize, next_sample: &mut dyn FnMut() -> (f32, f32))
where
    T: SizedSample + FromSample<f32>,
{
    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 added a commit that referenced this issue Jun 8, 2024
@tomara-x
Copy link
Owner Author

tomara-x commented Jun 9, 2024

[james earl jones voice] totes mcgoats

@tomara-x tomara-x closed this as completed Jun 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant