#[derive(Clone, Debug)]
pub struct DecodedPcm {
pub sample_rate: u32,
pub channels: Vec<Vec<f64>>,
pub channel_mask: Option<crate::channel_layout::ChannelMask>,
}
impl DecodedPcm {
pub fn into_audio(self) -> crate::audio::Audio {
let mut channels = self.channels;
for channel in &mut channels {
for sample in channel {
*sample = crate::audio::sanitize_sample(*sample);
}
}
crate::audio::Audio {
sample_rate: self.sample_rate,
channels,
bits_per_sample: 32,
sample_format: hound::SampleFormat::Float,
channel_mask: self.channel_mask,
}
}
pub fn n_channels(&self) -> usize {
self.channels.len()
}
pub fn frames(&self) -> usize {
self.channels.first().map(|c| c.len()).unwrap_or(0)
}
pub fn channel_layout(&self) -> crate::channel_layout::ChannelLayout {
self.channel_mask
.filter(|mask| mask.channels() == self.n_channels())
.map(crate::channel_layout::ChannelLayout::from_channel_mask)
.unwrap_or_else(|| {
crate::channel_layout::ChannelLayout::from_channel_count(self.n_channels())
})
}
pub fn effective_channel_mask(&self) -> Option<crate::channel_layout::ChannelMask> {
match self.channel_mask {
Some(mask) if mask.bits() == 0 || mask.channels() == self.n_channels() => Some(mask),
Some(_) => None,
None => self.channel_layout().mask(),
}
}
pub fn pan_info(&self) -> Option<Vec<crate::channel_layout::PanInfo>> {
self.effective_channel_mask()
.map(crate::channel_layout::ChannelMask::pan)
}
pub fn normalize_lengths(&mut self) {
let max = self.channels.iter().map(Vec::len).max().unwrap_or(0);
for ch in &mut self.channels {
if ch.len() < max {
ch.resize(max, 0.0);
}
}
}
}
#[inline]
pub fn f32_to_f64(v: f32) -> f64 {
v as f64
}
#[cfg(test)]
pub fn append_interleaved_f32(
channels: &mut [Vec<f64>],
interleaved: &[f32],
n_frames: usize,
n_ch: usize,
) {
debug_assert!(interleaved.len() >= n_frames * n_ch);
for i in 0..n_frames {
for ch in 0..n_ch {
channels[ch].push(f32_to_f64(interleaved[i * n_ch + ch]));
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn append_interleaved_stereo() {
let mut ch = vec![vec![], vec![]];
append_interleaved_f32(&mut ch, &[0.5, -0.5, 1.0, -1.0], 2, 2);
assert_eq!(ch[0], vec![0.5, 1.0]);
assert_eq!(ch[1], vec![-0.5, -1.0]);
}
#[test]
fn normalize_lengths_uses_longest_channel() {
let mut pcm = DecodedPcm {
sample_rate: 48000,
channels: vec![vec![1.0], vec![2.0, 3.0, 4.0]],
channel_mask: None,
};
pcm.normalize_lengths();
assert_eq!(pcm.channels[0], vec![1.0, 0.0, 0.0]);
assert_eq!(pcm.channels[1].len(), 3);
}
}