Added a pulse audio sink
This commit is contained in:
parent
7186738a22
commit
b4fd91ea13
|
@ -8,3 +8,5 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
num = "*"
|
||||
libpulse-binding = "2.16.0"
|
||||
libpulse-simple-binding = "*"
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
extern crate rusty_dsp;
|
||||
|
||||
use std::io;
|
||||
|
||||
use rusty_dsp::multiply::MultiplyConst;
|
||||
use rusty_dsp::sinks::SoundCardSink;
|
||||
use rusty_dsp::sources::SinSource;
|
||||
|
||||
fn main() {
|
||||
let source = SinSource::new(440.0, 48000.0);
|
||||
let mult = MultiplyConst::from(source, 0.3);
|
||||
let mut sink = SoundCardSink::from(mult, 48000);
|
||||
|
||||
sink.start().unwrap();
|
||||
}
|
|
@ -5,3 +5,7 @@ pub enum DspError {
|
|||
WouldBlock,
|
||||
Error(String),
|
||||
}
|
||||
|
||||
pub fn new_error(msg: &str) -> DspError {
|
||||
DspError::Error(msg.to_string())
|
||||
}
|
||||
|
|
15
src/lib.rs
15
src/lib.rs
|
@ -1,7 +1,8 @@
|
|||
mod amdemod;
|
||||
mod error;
|
||||
mod fillers;
|
||||
mod firfilter;
|
||||
mod multiply;
|
||||
mod resamplers;
|
||||
mod sources;
|
||||
pub mod amdemod;
|
||||
pub mod error;
|
||||
pub mod fillers;
|
||||
pub mod firfilter;
|
||||
pub mod multiply;
|
||||
pub mod resamplers;
|
||||
pub mod sinks;
|
||||
pub mod sources;
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
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()))?;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue