// RAW Audio // Copyright © 2021 Jeron Aldaron Lau. // // Licensed under the Boost Software License, Version 1.0 // (https://www.boost.org/LICENSE_1_0.txt or see accompanying file // LICENSE_BOOST_1_0.txt) use std::io::Write; use std::marker::PhantomData; use fon::chan::{Ch16, Ch32, Ch8, Channel}; use fon::{Frame, Stream}; use crate::pcm::{ ALaw, F32Be, F32Le, F64Be, F64Le, MuLaw, Pcm, S16Be, S16Le, S24Be, S24Le, S32Be, S32Le, U16Be, U16Le, U24Be, U24Le, U32Be, U32Le, S8, U8, }; /// Encoder for RAW Audio pub struct Encoder<W: Write, F: Frame, P: Pcm>(W, PhantomData<(F, P)>); // 32-bit Linear PCM channel. fn pcm_chan_32<C: Channel>(chan: C) -> i32 { let input = chan.to_f64() * 2147483647.5; if input < 0.0 { let input = -input; let fract = input % 1.0; let mut whole = input - fract; if fract > f64::EPSILON { whole += 1.0; } (-whole) as i32 } else { input as i32 } } impl<W: Write, F: Frame, P: Pcm> Encoder<W, F, P> { /// Create a new raw Audio encoder. pub fn new(writer: W, pcm: P) -> Self { let _ = pcm; Self(writer, PhantomData) } } impl<W: Write, F: Frame> Encoder<W, F, U8> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch8 = chan.into(); let chan: i8 = chan.into(); self.0.write_all(&[chan as u8 ^ 0x80])?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, S8> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch8 = chan.into(); let chan: i8 = chan.into(); self.0.write_all(&chan.to_le_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, MuLaw> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch16 = chan.into(); let chan: i16 = chan.into(); // reduce to 14 bits. let chan: u8 = match chan >> 2 { x if x <= -8159 => 0x00, x if x <= -4064 => ((x + 8159) >> 8) as u8, x if x <= -2016 => 0x10 | ((x + 4063) >> 7) as u8, x if x <= -992 => 0x20 | ((x + 2015) >> 6) as u8, x if x <= -480 => 0x30 | ((x + 991) >> 5) as u8, x if x <= -224 => 0x40 | ((x + 479) >> 4) as u8, x if x <= -96 => 0x50 | ((x + 223) >> 3) as u8, x if x <= -32 => 0x60 | ((x + 95) >> 2) as u8, x if x <= -1 => 0x70 | ((x + 31) >> 1) as u8, x if x <= 30 => 0xF0 | ((30 - x) >> 1) as u8, x if x <= 94 => 0xE0 | ((94 - x) >> 2) as u8, x if x <= 222 => 0xD0 | ((222 - x) >> 3) as u8, x if x <= 478 => 0xC0 | ((478 - x) >> 4) as u8, x if x <= 990 => 0xB0 | ((990 - x) >> 5) as u8, x if x <= 2014 => 0xA0 | ((2014 - x) >> 6) as u8, x if x <= 4062 => 0x90 | ((4062 - x) >> 7) as u8, x if x <= 8158 => 0x80 | ((8158 - x) >> 8) as u8, _ => 0x80, }; self.0.write_all(&[chan])?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, ALaw> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch16 = chan.into(); let chan: i16 = chan.into(); const C_CLIP: i16 = 32635; const LOG_TABLE: [u8; 128] = [ 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, ]; let mut chan = if chan == -32768 { -32767 } else { chan }; let sign = ((!chan) >> 8) as u8 & 0x80; if sign == 0 { chan = -chan; } if chan > C_CLIP { chan = C_CLIP; } let mut chan: u8 = if chan >= 256 { let exponent = LOG_TABLE[((chan >> 8) & 0x7F) as usize]; let mantissa = ((chan >> (exponent + 3)) & 0x0F) as u8; (exponent << 4) | mantissa } else { (chan >> 4) as u8 }; chan ^= sign ^ 0x55; self.0.write_all(&[chan])?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, U16Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch16 = chan.into(); let chan: i16 = chan.into(); self.0.write_all(&(chan ^ 0x8000u16 as i16).to_le_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, U16Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch16 = chan.into(); let chan: i16 = chan.into(); self.0.write_all(&(chan ^ 0x8000u16 as i16).to_be_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, S16Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch16 = chan.into(); let chan: i16 = chan.into(); self.0.write_all(&chan.to_le_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, S16Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch16 = chan.into(); let chan: i16 = chan.into(); self.0.write_all(&chan.to_be_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, U24Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan).to_le_bytes(); self.0.write_all(&[chan[0], chan[1], chan[2] ^ 0x80])?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, U24Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan).to_be_bytes(); self.0.write_all(&[chan[1] ^ 0x80, chan[2], chan[3]])?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, S24Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan).to_le_bytes(); self.0.write_all(&[chan[0], chan[1], chan[2]])?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, S24Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan).to_be_bytes(); self.0.write_all(&[chan[1], chan[2], chan[3]])?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, U32Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan) ^ (1 << 31); self.0.write_all(&chan.to_le_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, U32Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan) ^ (1 << 31); self.0.write_all(&chan.to_be_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, S32Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan); self.0.write_all(&chan.to_le_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, S32Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { let chan = pcm_chan_32(*chan); self.0.write_all(&chan.to_be_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, F32Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch32 = chan.into(); let chan: f32 = chan.into(); self.0.write_all(&chan.to_le_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, F32Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels().iter().cloned() { let chan: Ch32 = chan.into(); let chan: f32 = chan.into(); self.0.write_all(&chan.to_be_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, F64Le> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { self.0.write_all(&chan.to_f64().to_le_bytes())?; } } Ok(()) } } impl<W: Write, F: Frame> Encoder<W, F, F64Be> { /// Append encoded data from a stream to the output. This can be called /// multiple times to encode as needed instead of all at once. pub fn encode<S: Stream<F>>(&mut self, stream: S) -> std::io::Result<()> { assert!(stream.len().is_some()); for frame in stream.into_iter() { for chan in frame.channels() { self.0.write_all(&chan.to_f64().to_be_bytes())?; } } Ok(()) } }