raw_audio/
encoder.rs

1// RAW Audio
2// Copyright © 2021 Jeron Aldaron Lau.
3//
4// Licensed under the Boost Software License, Version 1.0
5// (https://www.boost.org/LICENSE_1_0.txt or see accompanying file
6// LICENSE_BOOST_1_0.txt)
7
8use std::io::Write;
9use std::marker::PhantomData;
10
11use fon::chan::{Ch16, Ch32, Ch8, Channel};
12use fon::{Frame, Stream};
13
14use crate::pcm::{
15    ALaw, F32Be, F32Le, F64Be, F64Le, MuLaw, Pcm, S16Be, S16Le, S24Be, S24Le,
16    S32Be, S32Le, U16Be, U16Le, U24Be, U24Le, U32Be, U32Le, S8, U8,
17};
18
19/// Encoder for RAW Audio
20pub struct Encoder<W: Write, F: Frame, P: Pcm>(W, PhantomData<(F, P)>);
21
22// 32-bit Linear PCM channel.
23fn pcm_chan_32<C: Channel>(chan: C) -> i32 {
24    let input = chan.to_f64() * 2147483647.5;
25
26    if input < 0.0 {
27        let input = -input;
28        let fract = input % 1.0;
29        let mut whole = input - fract;
30        if fract > f64::EPSILON {
31            whole += 1.0;
32        }
33        (-whole) as i32
34    } else {
35        input as i32
36    }
37}
38
39impl<W: Write, F: Frame, P: Pcm> Encoder<W, F, P> {
40    /// Create a new raw Audio encoder.
41    pub fn new(writer: W, pcm: P) -> Self {
42        let _ = pcm;
43        Self(writer, PhantomData)
44    }
45}
46
47impl<W: Write, F: Frame> Encoder<W, F, U8> {
48    /// Append encoded data from a stream to the output.  This can be called
49    /// multiple times to encode as needed instead of all at once.
50    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
51        assert!(stream.len().is_some());
52        for frame in stream.into_iter() {
53            for chan in frame.channels().iter().cloned() {
54                let chan: Ch8 = chan.into();
55                let chan: i8 = chan.into();
56                self.0.write_all(&[chan as u8 ^ 0x80])?;
57            }
58        }
59        Ok(())
60    }
61}
62
63impl<W: Write, F: Frame> Encoder<W, F, S8> {
64    /// Append encoded data from a stream to the output.  This can be called
65    /// multiple times to encode as needed instead of all at once.
66    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
67        assert!(stream.len().is_some());
68        for frame in stream.into_iter() {
69            for chan in frame.channels().iter().cloned() {
70                let chan: Ch8 = chan.into();
71                let chan: i8 = chan.into();
72                self.0.write_all(&chan.to_le_bytes())?;
73            }
74        }
75        Ok(())
76    }
77}
78
79impl<W: Write, F: Frame> Encoder<W, F, MuLaw> {
80    /// Append encoded data from a stream to the output.  This can be called
81    /// multiple times to encode as needed instead of all at once.
82    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
83        assert!(stream.len().is_some());
84        for frame in stream.into_iter() {
85            for chan in frame.channels().iter().cloned() {
86                let chan: Ch16 = chan.into();
87                let chan: i16 = chan.into();
88                // reduce to 14 bits.
89                let chan: u8 = match chan >> 2 {
90                    x if x <= -8159 => 0x00,
91                    x if x <= -4064 => ((x + 8159) >> 8) as u8,
92                    x if x <= -2016 => 0x10 | ((x + 4063) >> 7) as u8,
93                    x if x <= -992 => 0x20 | ((x + 2015) >> 6) as u8,
94                    x if x <= -480 => 0x30 | ((x + 991) >> 5) as u8,
95                    x if x <= -224 => 0x40 | ((x + 479) >> 4) as u8,
96                    x if x <= -96 => 0x50 | ((x + 223) >> 3) as u8,
97                    x if x <= -32 => 0x60 | ((x + 95) >> 2) as u8,
98                    x if x <= -1 => 0x70 | ((x + 31) >> 1) as u8,
99                    x if x <= 30 => 0xF0 | ((30 - x) >> 1) as u8,
100                    x if x <= 94 => 0xE0 | ((94 - x) >> 2) as u8,
101                    x if x <= 222 => 0xD0 | ((222 - x) >> 3) as u8,
102                    x if x <= 478 => 0xC0 | ((478 - x) >> 4) as u8,
103                    x if x <= 990 => 0xB0 | ((990 - x) >> 5) as u8,
104                    x if x <= 2014 => 0xA0 | ((2014 - x) >> 6) as u8,
105                    x if x <= 4062 => 0x90 | ((4062 - x) >> 7) as u8,
106                    x if x <= 8158 => 0x80 | ((8158 - x) >> 8) as u8,
107                    _ => 0x80,
108                };
109                self.0.write_all(&[chan])?;
110            }
111        }
112        Ok(())
113    }
114}
115
116impl<W: Write, F: Frame> Encoder<W, F, ALaw> {
117    /// Append encoded data from a stream to the output.  This can be called
118    /// multiple times to encode as needed instead of all at once.
119    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
120        assert!(stream.len().is_some());
121        for frame in stream.into_iter() {
122            for chan in frame.channels().iter().cloned() {
123                let chan: Ch16 = chan.into();
124                let chan: i16 = chan.into();
125
126                const C_CLIP: i16 = 32635;
127                const LOG_TABLE: [u8; 128] = [
128                    1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
129                    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
130                    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
131                    6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
132                    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
133                    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
134                    7, 7, 7, 7, 7, 7, 7, 7,
135                ];
136
137                let mut chan = if chan == -32768 { -32767 } else { chan };
138                let sign = ((!chan) >> 8) as u8 & 0x80;
139                if sign == 0 {
140                    chan = -chan;
141                }
142                if chan > C_CLIP {
143                    chan = C_CLIP;
144                }
145                let mut chan: u8 = if chan >= 256 {
146                    let exponent = LOG_TABLE[((chan >> 8) & 0x7F) as usize];
147                    let mantissa = ((chan >> (exponent + 3)) & 0x0F) as u8;
148                    (exponent << 4) | mantissa
149                } else {
150                    (chan >> 4) as u8
151                };
152                chan ^= sign ^ 0x55;
153
154                self.0.write_all(&[chan])?;
155            }
156        }
157        Ok(())
158    }
159}
160
161impl<W: Write, F: Frame> Encoder<W, F, U16Le> {
162    /// Append encoded data from a stream to the output.  This can be called
163    /// multiple times to encode as needed instead of all at once.
164    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
165        assert!(stream.len().is_some());
166        for frame in stream.into_iter() {
167            for chan in frame.channels().iter().cloned() {
168                let chan: Ch16 = chan.into();
169                let chan: i16 = chan.into();
170                self.0.write_all(&(chan ^ 0x8000u16 as i16).to_le_bytes())?;
171            }
172        }
173        Ok(())
174    }
175}
176
177impl<W: Write, F: Frame> Encoder<W, F, U16Be> {
178    /// Append encoded data from a stream to the output.  This can be called
179    /// multiple times to encode as needed instead of all at once.
180    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
181        assert!(stream.len().is_some());
182        for frame in stream.into_iter() {
183            for chan in frame.channels().iter().cloned() {
184                let chan: Ch16 = chan.into();
185                let chan: i16 = chan.into();
186                self.0.write_all(&(chan ^ 0x8000u16 as i16).to_be_bytes())?;
187            }
188        }
189        Ok(())
190    }
191}
192
193impl<W: Write, F: Frame> Encoder<W, F, S16Le> {
194    /// Append encoded data from a stream to the output.  This can be called
195    /// multiple times to encode as needed instead of all at once.
196    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
197        assert!(stream.len().is_some());
198        for frame in stream.into_iter() {
199            for chan in frame.channels().iter().cloned() {
200                let chan: Ch16 = chan.into();
201                let chan: i16 = chan.into();
202                self.0.write_all(&chan.to_le_bytes())?;
203            }
204        }
205        Ok(())
206    }
207}
208
209impl<W: Write, F: Frame> Encoder<W, F, S16Be> {
210    /// Append encoded data from a stream to the output.  This can be called
211    /// multiple times to encode as needed instead of all at once.
212    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
213        assert!(stream.len().is_some());
214        for frame in stream.into_iter() {
215            for chan in frame.channels().iter().cloned() {
216                let chan: Ch16 = chan.into();
217                let chan: i16 = chan.into();
218                self.0.write_all(&chan.to_be_bytes())?;
219            }
220        }
221        Ok(())
222    }
223}
224
225impl<W: Write, F: Frame> Encoder<W, F, U24Le> {
226    /// Append encoded data from a stream to the output.  This can be called
227    /// multiple times to encode as needed instead of all at once.
228    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
229        assert!(stream.len().is_some());
230        for frame in stream.into_iter() {
231            for chan in frame.channels() {
232                let chan = pcm_chan_32(*chan).to_le_bytes();
233                self.0.write_all(&[chan[0], chan[1], chan[2] ^ 0x80])?;
234            }
235        }
236        Ok(())
237    }
238}
239
240impl<W: Write, F: Frame> Encoder<W, F, U24Be> {
241    /// Append encoded data from a stream to the output.  This can be called
242    /// multiple times to encode as needed instead of all at once.
243    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
244        assert!(stream.len().is_some());
245        for frame in stream.into_iter() {
246            for chan in frame.channels() {
247                let chan = pcm_chan_32(*chan).to_be_bytes();
248                self.0.write_all(&[chan[1] ^ 0x80, chan[2], chan[3]])?;
249            }
250        }
251        Ok(())
252    }
253}
254
255impl<W: Write, F: Frame> Encoder<W, F, S24Le> {
256    /// Append encoded data from a stream to the output.  This can be called
257    /// multiple times to encode as needed instead of all at once.
258    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
259        assert!(stream.len().is_some());
260        for frame in stream.into_iter() {
261            for chan in frame.channels() {
262                let chan = pcm_chan_32(*chan).to_le_bytes();
263                self.0.write_all(&[chan[0], chan[1], chan[2]])?;
264            }
265        }
266        Ok(())
267    }
268}
269
270impl<W: Write, F: Frame> Encoder<W, F, S24Be> {
271    /// Append encoded data from a stream to the output.  This can be called
272    /// multiple times to encode as needed instead of all at once.
273    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
274        assert!(stream.len().is_some());
275        for frame in stream.into_iter() {
276            for chan in frame.channels() {
277                let chan = pcm_chan_32(*chan).to_be_bytes();
278                self.0.write_all(&[chan[1], chan[2], chan[3]])?;
279            }
280        }
281        Ok(())
282    }
283}
284
285impl<W: Write, F: Frame> Encoder<W, F, U32Le> {
286    /// Append encoded data from a stream to the output.  This can be called
287    /// multiple times to encode as needed instead of all at once.
288    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
289        assert!(stream.len().is_some());
290        for frame in stream.into_iter() {
291            for chan in frame.channels() {
292                let chan = pcm_chan_32(*chan) ^ (1 << 31);
293                self.0.write_all(&chan.to_le_bytes())?;
294            }
295        }
296        Ok(())
297    }
298}
299
300impl<W: Write, F: Frame> Encoder<W, F, U32Be> {
301    /// Append encoded data from a stream to the output.  This can be called
302    /// multiple times to encode as needed instead of all at once.
303    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
304        assert!(stream.len().is_some());
305        for frame in stream.into_iter() {
306            for chan in frame.channels() {
307                let chan = pcm_chan_32(*chan) ^ (1 << 31);
308                self.0.write_all(&chan.to_be_bytes())?;
309            }
310        }
311        Ok(())
312    }
313}
314
315impl<W: Write, F: Frame> Encoder<W, F, S32Le> {
316    /// Append encoded data from a stream to the output.  This can be called
317    /// multiple times to encode as needed instead of all at once.
318    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
319        assert!(stream.len().is_some());
320        for frame in stream.into_iter() {
321            for chan in frame.channels() {
322                let chan = pcm_chan_32(*chan);
323                self.0.write_all(&chan.to_le_bytes())?;
324            }
325        }
326        Ok(())
327    }
328}
329
330impl<W: Write, F: Frame> Encoder<W, F, S32Be> {
331    /// Append encoded data from a stream to the output.  This can be called
332    /// multiple times to encode as needed instead of all at once.
333    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
334        assert!(stream.len().is_some());
335        for frame in stream.into_iter() {
336            for chan in frame.channels() {
337                let chan = pcm_chan_32(*chan);
338                self.0.write_all(&chan.to_be_bytes())?;
339            }
340        }
341        Ok(())
342    }
343}
344
345impl<W: Write, F: Frame> Encoder<W, F, F32Le> {
346    /// Append encoded data from a stream to the output.  This can be called
347    /// multiple times to encode as needed instead of all at once.
348    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
349        assert!(stream.len().is_some());
350        for frame in stream.into_iter() {
351            for chan in frame.channels().iter().cloned() {
352                let chan: Ch32 = chan.into();
353                let chan: f32 = chan.into();
354                self.0.write_all(&chan.to_le_bytes())?;
355            }
356        }
357        Ok(())
358    }
359}
360
361impl<W: Write, F: Frame> Encoder<W, F, F32Be> {
362    /// Append encoded data from a stream to the output.  This can be called
363    /// multiple times to encode as needed instead of all at once.
364    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
365        assert!(stream.len().is_some());
366        for frame in stream.into_iter() {
367            for chan in frame.channels().iter().cloned() {
368                let chan: Ch32 = chan.into();
369                let chan: f32 = chan.into();
370                self.0.write_all(&chan.to_be_bytes())?;
371            }
372        }
373        Ok(())
374    }
375}
376
377impl<W: Write, F: Frame> Encoder<W, F, F64Le> {
378    /// Append encoded data from a stream to the output.  This can be called
379    /// multiple times to encode as needed instead of all at once.
380    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
381        assert!(stream.len().is_some());
382        for frame in stream.into_iter() {
383            for chan in frame.channels() {
384                self.0.write_all(&chan.to_f64().to_le_bytes())?;
385            }
386        }
387        Ok(())
388    }
389}
390
391impl<W: Write, F: Frame> Encoder<W, F, F64Be> {
392    /// Append encoded data from a stream to the output.  This can be called
393    /// multiple times to encode as needed instead of all at once.
394    pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> {
395        assert!(stream.len().is_some());
396        for frame in stream.into_iter() {
397            for chan in frame.channels() {
398                self.0.write_all(&chan.to_f64().to_be_bytes())?;
399            }
400        }
401        Ok(())
402    }
403}