use audio resampler on the write_to_disk example (#68)

This commit is contained in:
Théo Monnom
2023-05-13 01:48:06 +02:00
committed by GitHub
parent 76210c9f67
commit 2cad45cb39
4 changed files with 21 additions and 11 deletions
+18 -8
View File
@@ -2,6 +2,7 @@ use bytes::{BufMut, BytesMut};
use futures::StreamExt; use futures::StreamExt;
use livekit::prelude::*; use livekit::prelude::*;
use livekit::webrtc::audio_stream::native::NativeAudioStream; use livekit::webrtc::audio_stream::native::NativeAudioStream;
use livekit::webrtc::native::audio_resampler;
use std::env; use std::env;
use tokio::fs::File; use tokio::fs::File;
use tokio::io::{AsyncWriteExt, BufWriter}; use tokio::io::{AsyncWriteExt, BufWriter};
@@ -13,7 +14,7 @@ const FILE_PATH: &str = "record.wav";
pub struct WavHeader { pub struct WavHeader {
pub sample_rate: u32, pub sample_rate: u32,
pub bit_depth: u16, pub bit_depth: u16,
pub num_channels: u16, pub num_channels: u32,
} }
pub struct WavWriter { pub struct WavWriter {
@@ -41,9 +42,9 @@ impl WavWriter {
} }
fn write_header(&mut self) -> Result<(), std::io::Error> { 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.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; 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_slice(b"fmt ");
self.data.put_u32_le(16); // Subchunk1Size (16 for PCM) 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(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(self.header.sample_rate);
self.data.put_u32_le(byte_rate); self.data.put_u32_le(byte_rate);
self.data.put_u16_le(block_align); 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()); println!("Recording track {:?}", audio_track.sid());
let rtc_track = audio_track.rtc_track(); let rtc_track = audio_track.rtc_track();
// TODO(theomonnom): Remove hardcoded values
let header = WavHeader { let header = WavHeader {
sample_rate: 48000, sample_rate: 48000,
bit_depth: 16, 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 wav_writer = WavWriter::create(FILE_PATH, header).await?;
let mut audio_stream = NativeAudioStream::new(rtc_track); let mut audio_stream = NativeAudioStream::new(rtc_track);
let max_record = 5 * header.sample_rate * header.num_channels as u32; let max_record = 5 * header.sample_rate * header.num_channels as u32;
let mut sample_count = 0; let mut sample_count = 0;
'recv_loop: while let Some(frame) = audio_stream.next().await { 'recv_loop: while let Some(frame) = audio_stream.next().await {
for sample in frame.data { let data = resampler.remix_and_resample(
wav_writer.write_sample(sample).await.unwrap(); &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; sample_count += 1;
if sample_count >= max_record { if sample_count >= max_record {
+1 -1
View File
@@ -611,7 +611,7 @@ impl FfiServer {
fn new_audio_resampler( fn new_audio_resampler(
&'static self, &'static self,
new_resampler: proto::NewAudioResamplerRequest, _: proto::NewAudioResamplerRequest,
) -> FfiResult<proto::NewAudioResamplerResponse> { ) -> FfiResult<proto::NewAudioResamplerResponse> {
let resampler = audio_resampler::AudioResampler::default(); let resampler = audio_resampler::AudioResampler::default();
let resampler = Arc::new(Mutex::new(resampler)); let resampler = Arc::new(Mutex::new(resampler));
+1 -1
View File
@@ -33,7 +33,7 @@ impl AudioResampler {
dst_sample_rate as i32, 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)
} }
} }
} }
+1 -1
View File
@@ -33,7 +33,7 @@ size_t AudioResampler::remix_and_resample(const int16_t* src,
webrtc::voe::RemixAndResample(src, samples_per_channel, num_channels, webrtc::voe::RemixAndResample(src, samples_per_channel, num_channels,
sample_rate, &resampler_, &frame_); 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 { const int16_t* AudioResampler::data() const {