From 2cad45cb39c0df05a21d3ab8d409cb1b6f31c697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Monnom?= Date: Sat, 13 May 2023 01:48:06 +0200 Subject: [PATCH] use audio resampler on the write_to_disk example (#68) --- examples/save_to_disk/src/main.rs | 26 ++++++++++++++------ livekit-ffi/src/server/mod.rs | 2 +- livekit-webrtc/src/native/audio_resampler.rs | 2 +- webrtc-sys/src/audio_resampler.cpp | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/examples/save_to_disk/src/main.rs b/examples/save_to_disk/src/main.rs index 9ef0dd3..a9499f6 100644 --- a/examples/save_to_disk/src/main.rs +++ b/examples/save_to_disk/src/main.rs @@ -2,6 +2,7 @@ use bytes::{BufMut, BytesMut}; use futures::StreamExt; use livekit::prelude::*; use livekit::webrtc::audio_stream::native::NativeAudioStream; +use livekit::webrtc::native::audio_resampler; use std::env; use tokio::fs::File; use tokio::io::{AsyncWriteExt, BufWriter}; @@ -13,7 +14,7 @@ const FILE_PATH: &str = "record.wav"; pub struct WavHeader { pub sample_rate: u32, pub bit_depth: u16, - pub num_channels: u16, + pub num_channels: u32, } pub struct WavWriter { @@ -41,9 +42,9 @@ impl WavWriter { } fn write_header(&mut self) -> Result<(), std::io::Error> { - let byte_rate = (self.header.sample_rate + let byte_rate = self.header.sample_rate * self.header.bit_depth as u32 - * self.header.num_channels as u32); + * self.header.num_channels as u32; let block_align = byte_rate as u16 / self.header.sample_rate as u16; @@ -53,7 +54,7 @@ impl WavWriter { self.data.put_slice(b"fmt "); self.data.put_u32_le(16); // Subchunk1Size (16 for PCM) self.data.put_u16_le(1); // AudioFormat (1 for PCM) - self.data.put_u16_le(self.header.num_channels); + self.data.put_u16_le(self.header.num_channels as u16); self.data.put_u32_le(self.header.sample_rate); self.data.put_u32_le(byte_rate); self.data.put_u16_le(block_align); @@ -115,21 +116,30 @@ async fn record_track(audio_track: RemoteAudioTrack) -> Result<(), std::io::Erro println!("Recording track {:?}", audio_track.sid()); let rtc_track = audio_track.rtc_track(); - // TODO(theomonnom): Remove hardcoded values let header = WavHeader { sample_rate: 48000, bit_depth: 16, - num_channels: 1, + num_channels: 2, }; + let mut resampler = audio_resampler::AudioResampler::default(); let mut wav_writer = WavWriter::create(FILE_PATH, header).await?; let mut audio_stream = NativeAudioStream::new(rtc_track); let max_record = 5 * header.sample_rate * header.num_channels as u32; let mut sample_count = 0; 'recv_loop: while let Some(frame) = audio_stream.next().await { - for sample in frame.data { - wav_writer.write_sample(sample).await.unwrap(); + let data = resampler.remix_and_resample( + &frame.data, + frame.samples_per_channel, + frame.num_channels, + frame.sample_rate, + header.num_channels, + header.sample_rate, + ); + + for sample in data { + wav_writer.write_sample(*sample).await.unwrap(); sample_count += 1; if sample_count >= max_record { diff --git a/livekit-ffi/src/server/mod.rs b/livekit-ffi/src/server/mod.rs index 4a108c5..f737abc 100644 --- a/livekit-ffi/src/server/mod.rs +++ b/livekit-ffi/src/server/mod.rs @@ -611,7 +611,7 @@ impl FfiServer { fn new_audio_resampler( &'static self, - new_resampler: proto::NewAudioResamplerRequest, + _: proto::NewAudioResamplerRequest, ) -> FfiResult { let resampler = audio_resampler::AudioResampler::default(); let resampler = Arc::new(Mutex::new(resampler)); diff --git a/livekit-webrtc/src/native/audio_resampler.rs b/livekit-webrtc/src/native/audio_resampler.rs index dc1eab8..b05a03c 100644 --- a/livekit-webrtc/src/native/audio_resampler.rs +++ b/livekit-webrtc/src/native/audio_resampler.rs @@ -33,7 +33,7 @@ impl AudioResampler { dst_sample_rate as i32, ); - std::slice::from_raw_parts(self.sys_handle.data(), len) + std::slice::from_raw_parts(self.sys_handle.data(), len / 2) } } } diff --git a/webrtc-sys/src/audio_resampler.cpp b/webrtc-sys/src/audio_resampler.cpp index 6b0e0ad..cbb6060 100644 --- a/webrtc-sys/src/audio_resampler.cpp +++ b/webrtc-sys/src/audio_resampler.cpp @@ -33,7 +33,7 @@ size_t AudioResampler::remix_and_resample(const int16_t* src, webrtc::voe::RemixAndResample(src, samples_per_channel, num_channels, sample_rate, &resampler_, &frame_); - return frame_.num_channels() * frame_.samples_per_channel(); + return frame_.num_channels() * frame_.samples_per_channel() * sizeof(int16_t); } const int16_t* AudioResampler::data() const {