Kinda working tap/listen
+ Audio quality is bad and pretty choppy
This commit is contained in:
@@ -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}")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user