Kinda working tap/listen

+ Audio quality is bad and pretty choppy
This commit is contained in:
2025-08-23 18:23:37 -06:00
parent 009110e8e0
commit ccedbe0fb9
7 changed files with 405 additions and 111 deletions
+108
View File
@@ -0,0 +1,108 @@
use crate::output_buffer::OutputBuffer;
use crate::udp_connection::OpusUdpConnection;
use crate::{CIRC_BUFFER_SIZE, SAMPLE_RATE, SAMPLE_RATE_RAW, STEREO_FRAME_SIZE};
use anyhow::Error;
use audiopus::coder::Encoder;
use audiopus::{Application, Channels};
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use cpal::{FromSample, Host, Sample, StreamConfig};
use log::{error, info};
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
pub fn tap(
device: &str,
src_addr: SocketAddr,
dest_addr: SocketAddr,
host: Host,
) -> Result<(), Error> {
// Set up the input device and stream with the default input config.
let device = if device == "default" {
host.default_input_device()
} else {
host.input_devices()?
.find(|x| x.name().map(|y| y == device).unwrap_or(false))
}
.expect("failed to find input device");
info!("Input device: {}", device.name()?);
let config = device
.default_input_config()
.expect("Failed to get default input config");
let mut stream_config = StreamConfig::from(config.clone());
stream_config.sample_rate = cpal::SampleRate(SAMPLE_RATE_RAW as u32);
info!("Stream config: {stream_config:?}");
let udp_connection = OpusUdpConnection::new(src_addr, dest_addr)?;
let encoder = Encoder::new(SAMPLE_RATE, Channels::Stereo, Application::Audio)?;
let sound_buffer = Arc::new(Mutex::new(OutputBuffer::new(
STEREO_FRAME_SIZE,
encoder,
udp_connection,
)));
let err_fn = move |err| {
error!("an error occurred on stream: {err}");
};
let sound_buffer2 = sound_buffer.clone();
let stream = match config.sample_format() {
cpal::SampleFormat::I8 => device.build_input_stream(
&stream_config,
move |data, _: &_| write_input_data::<CIRC_BUFFER_SIZE, i8>(data, &sound_buffer2),
err_fn,
None,
)?,
cpal::SampleFormat::I16 => device.build_input_stream(
&stream_config,
move |data, _: &_| write_input_data::<CIRC_BUFFER_SIZE, i16>(data, &sound_buffer2),
err_fn,
None,
)?,
cpal::SampleFormat::I32 => device.build_input_stream(
&stream_config,
move |data, _: &_| write_input_data::<CIRC_BUFFER_SIZE, i32>(data, &sound_buffer2),
err_fn,
None,
)?,
cpal::SampleFormat::F32 => device.build_input_stream(
&stream_config,
move |data, _: &_| write_input_data::<CIRC_BUFFER_SIZE, f32>(data, &sound_buffer2),
err_fn,
None,
)?,
sample_format => {
return Err(anyhow::Error::msg(format!(
"Unsupported sample format '{sample_format}'"
)));
}
};
info!("Running tap...");
stream.play()?;
std::thread::park();
info!("Exiting...");
Ok(())
}
fn write_input_data<const N: usize, T>(
input: &[T],
ctx: &Arc<Mutex<OutputBuffer<N, OpusUdpConnection>>>,
) where
T: Sample,
f32: FromSample<T>,
{
if let Ok(mut ctx) = ctx.try_lock() {
let sample: Vec<f32> = input.iter().map(|s| f32::from_sample(*s)).collect();
if let Err(err) = ctx.write_data(&sample) {
error!("Got error when writing data to sound buffer: {err}")
}
}
}