rust_audio_api/nodes/
microphone.rs1use crate::nodes::resampler::{ResamplerState, RingIter};
2use crate::types::{AUDIO_UNIT_SIZE, AudioUnit};
3use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
4use cpal::{Stream, StreamConfig};
5use dasp::signal::Signal;
6use ringbuf::HeapRb;
7use ringbuf::traits::{Observer, Producer, Split};
8
9pub struct MicrophoneNode {
14 resampler: ResamplerState,
15 _stream: Stream,
16 gain: f32,
17}
18
19impl MicrophoneNode {
20 pub fn new(target_sample_rate: u32) -> Result<Self, anyhow::Error> {
25 let host = cpal::default_host();
26 let device = host
27 .default_input_device()
28 .expect("Microphone device not found");
29 let supported_config = device.default_input_config()?;
30 let input_rate = supported_config.sample_rate();
31 let config: StreamConfig = supported_config.into();
32 let channels = config.channels as usize;
33
34 println!("Microphone sample rate: {:?}", input_rate);
35
36 let capacity = input_rate as usize * channels;
38 let ringbuf = HeapRb::<f32>::new(capacity);
39 let (mut producer, consumer) = ringbuf.split();
40
41 let stream = device.build_input_stream(
42 &config,
43 move |data: &[f32], _: &cpal::InputCallbackInfo| {
44 for &sample in data {
45 if !producer.is_full() {
46 let _ = producer.try_push(sample);
47 }
48 }
49 },
50 |err| eprintln!("Microphone capture error: {}", err),
51 None,
52 )?;
53
54 stream.play()?;
55
56 let ring_iter = RingIter { consumer, channels };
57
58 let resampler = if input_rate != target_sample_rate {
59 let ring_buffer = dasp::ring_buffer::Fixed::from([[0.0; 2]; 100]);
60 let sinc = dasp::interpolate::sinc::Sinc::new(ring_buffer);
61 let converter =
62 ring_iter.from_hz_to_hz(sinc, input_rate as f64, target_sample_rate as f64);
63 ResamplerState::Resampling(Box::new(converter))
64 } else {
65 ResamplerState::Passthrough(ring_iter)
66 };
67
68 Ok(Self {
69 resampler,
70 _stream: stream,
71 gain: 1.0,
72 })
73 }
74
75 pub fn set_gain(&mut self, gain: f32) {
77 self.gain = gain;
78 }
79
80 #[inline(always)]
81 pub fn process(&mut self, _input: Option<&AudioUnit>, output: &mut AudioUnit) {
82 match &mut self.resampler {
83 ResamplerState::Passthrough(iter) => {
84 for out in output.iter_mut().take(AUDIO_UNIT_SIZE) {
85 *out = iter.next();
86 }
87 }
88 ResamplerState::Resampling(converter) => {
89 for out in output.iter_mut().take(AUDIO_UNIT_SIZE) {
90 *out = converter.next();
91 }
92 }
93 }
94
95 dasp::slice::map_in_place(&mut output[..], |frame| {
97 [frame[0] * self.gain, frame[1] * self.gain]
98 });
99 }
100}