use std::error::Error;
use crate::buffer::{AudioBuffer, AudioBufferOptions};
use crate::{SampleRate, RENDER_QUANTUM_SIZE};
#[cfg(not(test))]
use crossbeam_channel::Sender;
#[cfg(not(test))]
use crate::buffer::ChannelData;
#[cfg(not(test))]
use crate::io;
#[cfg(not(test))]
use cpal::{traits::StreamTrait, Sample, Stream};
use crossbeam_channel::{Receiver, TryRecvError};
pub struct Microphone {
receiver: Receiver<AudioBuffer>,
number_of_channels: usize,
sample_rate: SampleRate,
#[cfg(not(test))]
stream: Stream,
}
#[allow(clippy::non_send_fields_in_send_ty)]
unsafe impl Send for Microphone {}
impl Microphone {
#[cfg(not(test))]
pub fn new() -> Self {
let (stream, config, receiver) = io::build_input();
log::debug!("Input {:?}", config);
let sample_rate = SampleRate(config.sample_rate.0);
let number_of_channels = config.channels as usize;
Self {
receiver,
number_of_channels,
sample_rate,
stream,
}
}
pub fn suspend(&self) {
#[cfg(not(test))] self.stream.pause().unwrap()
}
pub fn resume(&self) {
#[cfg(not(test))] self.stream.play().unwrap()
}
}
#[cfg(not(test))]
impl Default for Microphone {
fn default() -> Self {
Self::new()
}
}
impl Iterator for Microphone {
type Item = Result<AudioBuffer, Box<dyn Error + Send + Sync>>;
fn next(&mut self) -> Option<Self::Item> {
let next = match self.receiver.try_recv() {
Ok(buffer) => {
buffer
}
Err(TryRecvError::Empty) => {
log::debug!("input frame delayed");
let options = AudioBufferOptions {
number_of_channels: self.number_of_channels,
length: RENDER_QUANTUM_SIZE,
sample_rate: self.sample_rate,
};
AudioBuffer::new(options)
}
Err(TryRecvError::Disconnected) => {
return None;
}
};
Some(Ok(next))
}
}
#[cfg(not(test))]
pub(crate) struct MicrophoneRender {
number_of_channels: usize,
sample_rate: SampleRate,
sender: Sender<AudioBuffer>,
}
#[cfg(not(test))]
impl MicrophoneRender {
pub fn new(
number_of_channels: usize,
sample_rate: SampleRate,
sender: Sender<AudioBuffer>,
) -> Self {
Self {
number_of_channels,
sample_rate,
sender,
}
}
pub fn render<S: Sample>(&self, data: &[S]) {
let mut channels = Vec::with_capacity(self.number_of_channels);
for i in 0..self.number_of_channels {
channels.push(ChannelData::from(
data.iter()
.skip(i)
.step_by(self.number_of_channels)
.map(|v| v.to_f32())
.collect(),
));
}
let buffer = AudioBuffer::from_channels(channels, self.sample_rate);
let result = self.sender.try_send(buffer); if result.is_err() {
log::debug!("input frame dropped");
}
}
}