| | |
| | | ) |
| | | } |
| | | |
| | | pub fn pcm_s16le_bytes_to_frames( |
| | | pcm_bytes: &[u8], |
| | | source_sample_rate_hz: u32, |
| | | source_num_channels: u32, |
| | | target_sample_rate_hz: u32, |
| | | target_num_channels: u16, |
| | | ) -> Result<Vec<PcmFrame>> { |
| | | if source_sample_rate_hz == 0 { |
| | | return Err(anyhow!("pcm_s16le source sample rate is zero")); |
| | | } |
| | | if source_num_channels == 0 { |
| | | return Err(anyhow!("pcm_s16le source channel count is zero")); |
| | | } |
| | | if pcm_bytes.len() % 2 != 0 { |
| | | return Err(anyhow!("pcm_s16le payload has odd byte length")); |
| | | } |
| | | let samples: Vec<i16> = pcm_bytes |
| | | .chunks_exact(2) |
| | | .map(|chunk| i16::from_le_bytes([chunk[0], chunk[1]])) |
| | | .collect(); |
| | | if samples.is_empty() { |
| | | return Ok(Vec::new()); |
| | | } |
| | | let source_channels = u16::try_from(source_num_channels) |
| | | .map_err(|_| anyhow!("unsupported pcm_s16le channel count {source_num_channels}"))?; |
| | | let mut target_samples = remap_channels(samples, source_channels, target_num_channels); |
| | | target_samples = resample_linear( |
| | | target_samples, |
| | | source_sample_rate_hz, |
| | | target_sample_rate_hz, |
| | | target_num_channels, |
| | | ); |
| | | Ok(chunk_pcm_samples( |
| | | target_samples, |
| | | target_sample_rate_hz, |
| | | target_num_channels, |
| | | )) |
| | | } |
| | | |
| | | fn decode_audio_frames( |
| | | audio_bytes: &[u8], |
| | | source_kind: &'static str, |
| | |
| | | |
| | | #[cfg(test)] |
| | | mod tests { |
| | | use super::load_pre_recorded_frames; |
| | | use super::{load_pre_recorded_frames, pcm_s16le_bytes_to_frames}; |
| | | |
| | | #[tokio::test] |
| | | async fn load_pre_recorded_frames_reads_local_wav() { |
| | |
| | | assert!(loaded.diagnostics.debug_source_path.is_some()); |
| | | assert!(loaded.diagnostics.debug_pcm_wav_path.is_some()); |
| | | } |
| | | |
| | | #[test] |
| | | fn pcm_s16le_bytes_to_frames_resamples_elevenlabs_pcm_to_livekit_frames() { |
| | | let mut pcm = Vec::new(); |
| | | for index in 0..4410 { |
| | | let sample = if index % 2 == 0 { 1024_i16 } else { -1024_i16 }; |
| | | pcm.extend_from_slice(&sample.to_le_bytes()); |
| | | } |
| | | |
| | | let frames = pcm_s16le_bytes_to_frames(&pcm, 44_100, 1, 48_000, 1).expect("pcm frames"); |
| | | |
| | | assert!(!frames.is_empty()); |
| | | assert_eq!(frames[0].sample_rate, 48_000); |
| | | assert_eq!(frames[0].num_channels, 1); |
| | | assert_eq!(frames[0].samples_per_channel, 960); |
| | | } |
| | | } |