75 lines
2.4 KiB
Rust
75 lines
2.4 KiB
Rust
extern crate libpulse_binding as pulse;
|
||
extern crate libpulse_simple_binding as psimple;
|
||
|
||
use psimple::Simple;
|
||
use pulse::sample;
|
||
use pulse::stream::Direction;
|
||
|
||
use super::error::{new_error, DspError};
|
||
|
||
pub struct SoundCardSink<'a> {
|
||
iterator: Box<dyn Iterator<Item = Result<f32, DspError>> + 'a>,
|
||
sampling_rate: u32,
|
||
}
|
||
|
||
impl<'a> SoundCardSink<'a> {
|
||
pub fn from<I>(iterator1: I, sampling_rate: u32) -> SoundCardSink<'a>
|
||
where
|
||
I: Iterator<Item = Result<f32, DspError>> + 'a,
|
||
{
|
||
SoundCardSink {
|
||
iterator: Box::new(iterator1),
|
||
sampling_rate: sampling_rate,
|
||
}
|
||
}
|
||
|
||
pub fn start(&mut self) -> Result<(), DspError> {
|
||
let spec = sample::Spec {
|
||
format: sample::SAMPLE_FLOAT32NE,
|
||
channels: 1,
|
||
rate: self.sampling_rate,
|
||
};
|
||
if !spec.is_valid() {
|
||
return Err(new_error("Sample spec is invalid."));
|
||
}
|
||
|
||
let stream = Simple::new(
|
||
None, // Use the default server
|
||
"Rusty DSP", // Our application’s name
|
||
Direction::Playback, // We want a playback stream
|
||
None, // Use the default device
|
||
"Sound Card Sink", // Description of our stream
|
||
&spec, // Our sample format
|
||
None, // Use default channel map
|
||
None, // Use default buffering attributes
|
||
)
|
||
.map_err(|e| DspError::Error(e.to_string().unwrap()))?;
|
||
|
||
loop {
|
||
let mut chunk = Vec::new();
|
||
|
||
while chunk.len() < 64 {
|
||
let mut sample = Some(Err(DspError::WouldBlock));
|
||
while sample == Some(Err(DspError::WouldBlock)) {
|
||
sample = self.iterator.next();
|
||
}
|
||
|
||
let value = match sample {
|
||
Some(Ok(f)) => f,
|
||
None => return Ok(()),
|
||
Some(Err(DspError::WouldBlock)) => {
|
||
return Err(new_error("Unexpected WouldBlock."))
|
||
}
|
||
Some(Err(e)) => return Err(e),
|
||
};
|
||
|
||
chunk.extend_from_slice(value.to_ne_bytes().as_ref());
|
||
}
|
||
|
||
stream
|
||
.write(chunk.as_slice())
|
||
.map_err(|e| DspError::Error(e.to_string().unwrap()))?;
|
||
}
|
||
}
|
||
}
|