floaout/
lpcm.rs

1use crate::io::{ReadExt, WriteExt};
2use mycrc::CRC;
3use std::io::{Error, ErrorKind, Read, Result, Write};
4use std::ops::{AddAssign, Mul};
5
6/// Lpcm Sample
7pub trait Sample:
8    Sized + Default + AddAssign + Mul<Output = Self> + Clone + Copy + PartialEq
9{
10    fn from_f32(n: f32) -> Self;
11    fn from_f64(n: f64) -> Self;
12    fn to_f32(self) -> f32;
13    fn to_f64(self) -> f64;
14    fn read<R: Read>(reader: &mut R) -> Result<Self>;
15    fn write<W: Write>(self, writer: &mut W) -> Result<()>;
16
17    fn read_and_calc_bytes<R: Read>(reader: &mut R, crc: &mut CRC<u32>) -> Result<Self>;
18    fn write_and_calc_bytes<W: Write>(self, writer: &mut W, crc: &mut CRC<u32>) -> Result<()>;
19}
20
21macro_rules! le_sample_impl {
22    ( $( $t:ty ),* ) => ($(
23        impl Sample for $t {
24            fn from_f32(n: f32) -> Self {
25                n as $t
26            }
27
28            fn from_f64(n: f64) -> Self {
29                n as $t
30            }
31
32            fn to_f32(self) -> f32 {
33                self as f32
34            }
35
36            fn to_f64(self) -> f64 {
37                self as f64
38            }
39
40            fn read<R: Read>(reader: &mut R) -> Result<Self> {
41                reader.read_le()
42            }
43            fn write<W: Write>(self, writer: &mut W) -> Result<()> {
44                writer.write_le(self)
45            }
46
47            fn read_and_calc_bytes<R: Read>(reader: &mut R, crc: &mut CRC<u32>) -> Result<Self> {
48                reader.read_le_and_calc_bytes(crc)
49            }
50            fn write_and_calc_bytes<W: Write>(self, writer: &mut W, crc: &mut CRC<u32>) -> Result<()> {
51                writer.write_le_and_calc_bytes(self, crc)
52            }
53        }
54    )*)
55}
56
57le_sample_impl!(f32, f64);
58
59/// Lpcm Frame
60#[derive(Clone, Debug, PartialEq)]
61pub struct Frame<S: Sample>(pub Vec<S>);
62
63impl<S: Sample> From<Frame<S>> for Vec<S> {
64    fn from(value: Frame<S>) -> Self {
65        value.0
66    }
67}
68
69impl<S: Sample> From<Vec<S>> for Frame<S> {
70    fn from(value: Vec<S>) -> Self {
71        Frame(value)
72    }
73}
74
75impl<S: Sample> Frame<S> {
76    pub fn add(&mut self, other: Self) -> Result<()> {
77        if self.0.len() != other.0.len() {
78            return Err(Error::new(
79                ErrorKind::Other,
80                format!(
81                    "The frames are not the same length. expected `{:?}`, found `{:?}`",
82                    self.0.len(),
83                    other.0.len()
84                ),
85            ));
86        }
87
88        for i in 0..self.0.len() {
89            self.0[i] += other.0[i];
90        }
91
92        Ok(())
93    }
94}
95
96#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
97pub enum LpcmKind {
98    F32LE,
99    F64LE,
100    I16LE,
101}
102
103impl LpcmKind {
104    pub fn read<R: Read>(reader: &mut R) -> Result<Self> {
105        let value: u8 = reader.read_le()?;
106        Ok(match value {
107            0 => Self::F32LE,
108            1 => Self::F64LE,
109            3 => Self::I16LE,
110            _ => return Err(ErrorKind::InvalidData.into()),
111        })
112    }
113    pub fn read_and_calc_bytes<R: Read>(reader: &mut R, crc: &mut CRC<u32>) -> Result<Self> {
114        let value: u8 = reader.read_le_and_calc_bytes(crc)?;
115        Ok(match value {
116            0 => Self::F32LE,
117            1 => Self::F64LE,
118            3 => Self::I16LE,
119            _ => return Err(ErrorKind::InvalidData.into()),
120        })
121    }
122
123    pub fn write<W: Write>(self, writer: &mut W) -> Result<()> {
124        writer.write_le(self.to_u8())
125    }
126    pub fn write_and_calc_bytes<W: Write>(self, writer: &mut W, crc: &mut CRC<u32>) -> Result<()> {
127        writer.write_le_and_calc_bytes(self.to_u8(), crc)
128    }
129
130    pub fn from_u8(value: u8) -> Self {
131        match value {
132            0 => Self::F32LE,
133            1 => Self::F64LE,
134            3 => Self::I16LE,
135            _ => unimplemented!(),
136        }
137    }
138
139    pub const fn to_u8(self) -> u8 {
140        match self {
141            Self::F32LE => 0,
142            Self::F64LE => 1,
143            Self::I16LE => 3,
144        }
145    }
146
147    pub const fn format_tag(&self) -> u16 {
148        match self {
149            Self::F32LE => 3,
150            Self::F64LE => 3,
151            Self::I16LE => 1,
152        }
153    }
154
155    pub const fn bits_per_sample(&self) -> u16 {
156        match self {
157            Self::F32LE => 32,
158            Self::F64LE => 64,
159            Self::I16LE => 16,
160        }
161    }
162
163    pub fn from_format_tag_and_bits_per_sample(format_tag: u16, bits_per_sample: u16) -> Self {
164        match format_tag {
165            1 => match bits_per_sample {
166                16 => Self::I16LE,
167                _ => unimplemented!(),
168            },
169            3 => match bits_per_sample {
170                32 => Self::F32LE,
171                64 => Self::F64LE,
172                _ => unimplemented!(),
173            },
174            _ => unimplemented!(),
175        }
176    }
177}