audio: move audio task into separate audio module

This commit is contained in:
2026-06-08 15:04:04 +02:00
parent aba2194032
commit 34d58e5d66
3 changed files with 93 additions and 91 deletions
+88
View File
@@ -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
})
}