audio: move audio task into separate audio module
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
use jack::{AudioIn, ClientOptions};
|
||||
use oximedia_metering::vu_meter::VuMeter;
|
||||
use tokio::sync::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JackClientRef {
|
||||
killswitch: Option<oneshot::Sender<()>>
|
||||
}
|
||||
|
||||
impl Drop for JackClientRef {
|
||||
fn drop(&mut self) {
|
||||
self.killswitch.take().unwrap().send(()).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AudioInputControl {
|
||||
volume_src: watch::Receiver<f64>,
|
||||
_jack_client: JackClientRef
|
||||
}
|
||||
|
||||
impl AudioInputControl {
|
||||
pub async fn next(&mut self) -> f64 {
|
||||
self.volume_src.changed().await.unwrap();
|
||||
*self.volume_src.borrow_and_update()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MicStream {
|
||||
pub src: mpsc::Receiver<Vec<f32>>,
|
||||
pub sample_rate: u32
|
||||
}
|
||||
|
||||
pub async fn start_audio_input(messages: &mpsc::Sender<String>) -> (AudioInputControl, MicStream) {
|
||||
|
||||
let (exit_tx, exit_rx) = oneshot::channel();
|
||||
|
||||
let (mic_audio_sink, mic_audio_src) = mpsc::channel(32);
|
||||
let (volume_sink, volume_src) = watch::channel(0.);
|
||||
|
||||
let (client, _status) = jack::Client::new("Eva-Cohost", ClientOptions::default() | ClientOptions::SESSION_ID).unwrap();
|
||||
let mic_port = client.register_port("microphone-in", AudioIn::default()).unwrap();
|
||||
let rate = client.sample_rate();
|
||||
|
||||
if let Ok(_) = client.connect_ports_by_name("mixxx-mic-1:capture_MONO", mic_port.name().unwrap().as_str()) {
|
||||
messages.send("Connected to audio.".into()).await.unwrap();
|
||||
} else {
|
||||
messages.send("Failed to reconnect to audio.".into()).await.unwrap();
|
||||
}
|
||||
|
||||
let mut meter = VuMeter::new(rate.into(), 1, None);
|
||||
|
||||
let handler = jack::contrib::ClosureProcessHandler::new(move |_client, scope| {
|
||||
if mic_port.connected_count().unwrap() > 0 {
|
||||
let buf: Vec<_> = mic_port.as_slice(scope).iter().copied().collect();
|
||||
meter.process_interleaved(&buf);
|
||||
mic_audio_sink.blocking_send(buf).unwrap();
|
||||
|
||||
volume_sink.send_if_modified(|v| {
|
||||
let next_vu = meter.channel_vu(0).unwrap();
|
||||
if *v != next_vu {
|
||||
*v = next_vu;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
jack::Control::Continue
|
||||
});
|
||||
|
||||
tokio::spawn(async move {
|
||||
let async_client = client.activate_async((), handler).unwrap();
|
||||
|
||||
exit_rx.await.unwrap();
|
||||
|
||||
async_client.deactivate().unwrap();
|
||||
});
|
||||
|
||||
(AudioInputControl {
|
||||
volume_src,
|
||||
_jack_client: JackClientRef { killswitch: Some(exit_tx) }
|
||||
}, MicStream {
|
||||
sample_rate: rate,
|
||||
src: mic_audio_src
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user