use crate::Error;
use crate::audio::Frame;
use crate::metadata::{BlockList, ChannelMask, SeekTable};
use bitstream_io::{BitRead, SignedBitCount};
use std::collections::VecDeque;
use std::fs::File;
use std::io::BufReader;
use std::num::NonZero;
use std::path::Path;
pub use crate::metadata::Metadata;
trait SignedInteger:
bitstream_io::SignedInteger + Into<i64> + std::ops::AddAssign + std::ops::Neg<Output = Self>
{
fn from_i64(i: i64) -> Self;
fn from_u32(u: u32) -> Self;
}
impl SignedInteger for i32 {
#[inline(always)]
fn from_i64(i: i64) -> i32 {
i as i32
}
#[inline(always)]
fn from_u32(u: u32) -> i32 {
u as i32
}
}
impl SignedInteger for i64 {
#[inline(always)]
fn from_i64(i: i64) -> i64 {
i
}
#[inline(always)]
fn from_u32(u: u32) -> i64 {
u as i64
}
}
#[derive(Clone)]
pub struct FlacByteReader<R, E> {
decoder: Decoder<R>,
buf: VecDeque<u8>,
endianness: std::marker::PhantomData<E>,
frames_start: Option<u64>,
}
impl<R: std::io::Read, E: crate::byteorder::Endianness> FlacByteReader<R, E> {
#[inline]
pub fn new(mut reader: R) -> Result<Self, Error> {
let blocklist = BlockList::read(reader.by_ref())?;
Ok(Self {
decoder: Decoder::new(reader, blocklist),
buf: VecDeque::default(),
endianness: std::marker::PhantomData,
frames_start: None,
})
}
#[inline]
pub fn endian(reader: R, _endian: E) -> Result<Self, Error> {
Self::new(reader)
}
#[inline]
pub fn metadata(&self) -> &BlockList {
self.decoder.metadata()
}
}
impl<R: std::io::Read + std::io::Seek, E: crate::byteorder::Endianness> FlacByteReader<R, E> {
pub fn new_seekable(mut reader: R) -> Result<Self, Error> {
let blocklist = BlockList::read(reader.by_ref())?;
let frames_start = reader.stream_position()?;
Ok(Self {
decoder: Decoder::new(reader, blocklist),
buf: VecDeque::default(),
endianness: std::marker::PhantomData,
frames_start: Some(frames_start),
})
}
}
impl<R: std::io::Read, E: crate::byteorder::Endianness> Metadata for FlacByteReader<R, E> {
#[inline]
fn channel_count(&self) -> u8 {
self.decoder.channel_count().get()
}
#[inline]
fn channel_mask(&self) -> ChannelMask {
self.decoder.channel_mask()
}
#[inline]
fn sample_rate(&self) -> u32 {
self.decoder.sample_rate()
}
#[inline]
fn bits_per_sample(&self) -> u32 {
self.decoder.bits_per_sample()
}
#[inline]
fn total_samples(&self) -> Option<u64> {
self.decoder.total_samples().map(|s| s.get())
}
#[inline]
fn md5(&self) -> Option<&[u8; 16]> {
self.decoder.md5()
}
}
impl<E: crate::byteorder::Endianness> FlacByteReader<BufReader<File>, E> {
#[inline]
pub fn open<P: AsRef<Path>>(path: P, _endianness: E) -> Result<Self, Error> {
FlacByteReader::new_seekable(BufReader::new(File::open(path.as_ref())?))
}
}
impl<R: std::io::Read, E: crate::byteorder::Endianness> std::io::Read for FlacByteReader<R, E> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if self.buf.is_empty() {
match self.decoder.read_frame()? {
Some(frame) => {
self.buf.resize(frame.bytes_len(), 0);
frame.to_buf::<E>(self.buf.make_contiguous());
self.buf.read(buf)
}
None => Ok(0),
}
} else {
self.buf.read(buf)
}
}
}
impl<R: std::io::Read, E: crate::byteorder::Endianness> std::io::BufRead for FlacByteReader<R, E> {
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
if self.buf.is_empty() {
match self.decoder.read_frame()? {
Some(frame) => {
self.buf.resize(frame.bytes_len(), 0);
frame.to_buf::<E>(self.buf.make_contiguous());
self.buf.fill_buf()
}
None => Ok(&[]),
}
} else {
self.buf.fill_buf()
}
}
fn consume(&mut self, amt: usize) {
self.buf.consume(amt)
}
}
#[derive(Clone)]
pub struct FlacSampleReader<R> {
decoder: Decoder<R>,
buf: Vec<i32>,
frames_start: Option<u64>,
}
impl<R: std::io::Read> FlacSampleReader<R> {
#[inline]
pub fn new(mut reader: R) -> Result<Self, Error> {
let blocklist = BlockList::read(reader.by_ref())?;
Ok(Self {
decoder: Decoder::new(reader, blocklist),
buf: Vec::default(),
frames_start: None,
})
}
#[inline]
pub fn metadata(&self) -> &BlockList {
self.decoder.metadata()
}
#[inline]
pub fn read(&mut self, samples: &mut [i32]) -> Result<usize, Error> {
if self.buf.is_empty() {
match self.decoder.read_frame()? {
Some(frame) => {
self.buf.extend(frame.iter());
}
None => return Ok(0),
}
}
let to_consume = samples.len().min(self.buf.len());
for (i, o) in samples.iter_mut().zip(self.buf.drain(0..to_consume)) {
*i = o;
}
Ok(to_consume)
}
pub fn read_to_end(&mut self, buf: &mut Vec<i32>) -> Result<usize, Error> {
let mut amt_read = 0;
loop {
match self.fill_buf()? {
[] => break Ok(amt_read),
decoded => {
let decoded_len = decoded.len();
buf.extend_from_slice(decoded);
amt_read += decoded_len;
self.consume(decoded_len);
}
}
}
}
#[inline]
pub fn fill_buf(&mut self) -> Result<&[i32], Error> {
if self.buf.is_empty() {
match self.decoder.read_frame()? {
Some(frame) => {
self.buf.extend(frame.iter());
}
None => return Ok(&[]),
}
}
Ok(self.buf.as_mut_slice())
}
#[inline]
pub fn consume(&mut self, amt: usize) {
self.buf.drain(0..amt);
}
}
impl<R: std::io::Read + std::io::Seek> FlacSampleReader<R> {
pub fn new_seekable(mut reader: R) -> Result<Self, Error> {
let blocklist = BlockList::read(reader.by_ref())?;
let frames_start = reader.stream_position()?;
Ok(Self {
decoder: Decoder::new(reader, blocklist),
buf: Vec::default(),
frames_start: Some(frames_start),
})
}
}
impl FlacSampleReader<BufReader<File>> {
#[inline]
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
FlacSampleReader::new_seekable(BufReader::new(File::open(path.as_ref())?))
}
}
impl<R: std::io::Read> Metadata for FlacSampleReader<R> {
#[inline]
fn channel_count(&self) -> u8 {
self.decoder.channel_count().get()
}
#[inline]
fn channel_mask(&self) -> ChannelMask {
self.decoder.channel_mask()
}
#[inline]
fn sample_rate(&self) -> u32 {
self.decoder.sample_rate()
}
#[inline]
fn bits_per_sample(&self) -> u32 {
self.decoder.bits_per_sample()
}
#[inline]
fn total_samples(&self) -> Option<u64> {
self.decoder.total_samples().map(|s| s.get())
}
#[inline]
fn md5(&self) -> Option<&[u8; 16]> {
self.decoder.md5()
}
}
impl<R: std::io::Read> IntoIterator for FlacSampleReader<R> {
type IntoIter = FlacSampleIterator<R>;
type Item = Result<i32, Error>;
fn into_iter(self) -> FlacSampleIterator<R> {
FlacSampleIterator {
decoder: self.decoder,
buf: self.buf.into(),
}
}
}
#[derive(Clone)]
pub struct FlacSampleIterator<R> {
decoder: Decoder<R>,
buf: VecDeque<i32>,
}
impl<R: std::io::Read> Metadata for FlacSampleIterator<R> {
fn channel_count(&self) -> u8 {
self.decoder.channel_count().get()
}
fn sample_rate(&self) -> u32 {
self.decoder.sample_rate()
}
fn bits_per_sample(&self) -> u32 {
self.decoder.bits_per_sample()
}
fn total_samples(&self) -> Option<u64> {
self.decoder.total_samples().map(|s| s.get())
}
fn md5(&self) -> Option<&[u8; 16]> {
self.decoder.md5()
}
}
impl<R: std::io::Read> Iterator for FlacSampleIterator<R> {
type Item = Result<i32, Error>;
#[inline]
fn next(&mut self) -> Option<Result<i32, Error>> {
self.buf.pop_front().map_or_else(
|| match self.decoder.read_frame() {
Ok(Some(frame)) => {
self.buf.extend(frame.iter());
self.buf.pop_front().map(Ok)
}
Err(e) => Some(Err(e)),
Ok(None) => None,
},
|i| Some(Ok(i)),
)
}
}
impl<R: std::io::Read + std::io::Seek, E: crate::byteorder::Endianness> std::io::Seek
for FlacByteReader<R, E>
{
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
use std::cmp::Ordering;
let Self { decoder, buf, .. } = self;
let streaminfo = decoder.blocks.streaminfo();
let bytes_per_pcm_frame: u64 = (u32::from(streaminfo.bits_per_sample).div_ceil(8)
* u32::from(streaminfo.channels.get()))
.into();
let desired_pos: u64 = match pos {
std::io::SeekFrom::Start(pos) => pos,
std::io::SeekFrom::Current(pos) => {
let original_pos: u64 =
(decoder.current_sample * bytes_per_pcm_frame) - (buf.len() as u64);
match pos.cmp(&0) {
Ordering::Less => {
original_pos
.checked_sub(pos.unsigned_abs())
.ok_or(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"cannot seek below byte 0",
))?
}
Ordering::Equal => return Ok(original_pos),
Ordering::Greater => {
original_pos
.checked_add(pos.unsigned_abs())
.ok_or(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"seek offset too large",
))?
}
}
}
std::io::SeekFrom::End(pos) => {
let max_pos: u64 = decoder.total_samples().map(|s| s.get()).ok_or_else(|| {
std::io::Error::new(std::io::ErrorKind::NotSeekable, "total samples not known")
})?;
match pos.cmp(&0) {
Ordering::Less => max_pos.checked_sub(pos.unsigned_abs()).ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"cannot seek below byte 0",
)
})?,
Ordering::Equal => max_pos,
Ordering::Greater => {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"cannot seek beyond end of file",
));
}
}
}
};
let mut new_pos = decoder.seek(
self.frames_start
.ok_or(std::io::Error::from(std::io::ErrorKind::NotSeekable))?,
desired_pos / bytes_per_pcm_frame,
)? * bytes_per_pcm_frame;
buf.clear();
while new_pos < desired_pos {
use std::io::BufRead;
let buf = self.fill_buf()?;
if !buf.is_empty() {
let to_skip = (usize::try_from(desired_pos - new_pos).unwrap()).min(buf.len());
self.consume(to_skip);
new_pos += to_skip as u64;
} else {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"stream exhausted before sample reached",
));
}
}
Ok(desired_pos)
}
}
impl<R: std::io::Read + std::io::Seek> FlacSampleReader<R> {
pub fn seek(&mut self, sample: u64) -> Result<(), Error> {
let channels: u8 = self.channel_count();
let mut pos = self.decoder.seek(
self.frames_start
.ok_or(std::io::Error::from(std::io::ErrorKind::NotSeekable))?,
sample,
)?;
self.buf.clear();
while sample > pos {
let buf = self.fill_buf()?;
match buf.len() / usize::from(channels) {
0 => {
return Err(Error::InvalidSeek);
}
buf_samples => {
let to_consume = buf_samples.min((sample - pos).try_into().unwrap());
self.consume(to_consume * usize::from(channels));
pos += to_consume as u64;
}
}
}
Ok(())
}
}
#[derive(Clone)]
pub struct FlacChannelReader<R> {
decoder: Decoder<R>,
consumed: usize,
frames_start: Option<u64>,
}
impl<R: std::io::Read> FlacChannelReader<R> {
#[inline]
pub fn new(mut reader: R) -> Result<Self, Error> {
let blocklist = BlockList::read(reader.by_ref())?;
Ok(Self {
decoder: Decoder::new(reader, blocklist),
consumed: 0,
frames_start: None,
})
}
#[inline]
pub fn metadata(&self) -> &BlockList {
self.decoder.metadata()
}
#[inline]
pub fn fill_buf(&mut self) -> Result<Vec<&[i32]>, Error> {
if self.consumed < self.decoder.buf.pcm_frames() {
Ok(self
.decoder
.buf
.channels()
.map(|c| &c[self.consumed..])
.collect())
} else {
self.consumed = 0;
let channels = usize::from(self.decoder.channel_count().get());
match self.decoder.read_frame()? {
Some(frame) => Ok(frame.channels().collect()),
None => Ok(vec![&[]; channels]),
}
}
}
#[inline]
pub fn consume(&mut self, amt: usize) {
self.consumed += amt;
}
}
impl<R: std::io::Read + std::io::Seek> FlacChannelReader<R> {
pub fn new_seekable(mut reader: R) -> Result<Self, Error> {
let blocklist = BlockList::read(reader.by_ref())?;
let frames_start = reader.stream_position()?;
Ok(Self {
decoder: Decoder::new(reader, blocklist),
consumed: 0,
frames_start: Some(frames_start),
})
}
}
impl FlacChannelReader<BufReader<File>> {
#[inline]
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
FlacChannelReader::new_seekable(BufReader::new(File::open(path.as_ref())?))
}
}
impl<R: std::io::Read + std::io::Seek> FlacChannelReader<R> {
pub fn seek(&mut self, sample: u64) -> Result<(), Error> {
let mut pos = self.decoder.seek(
self.frames_start
.ok_or(std::io::Error::from(std::io::ErrorKind::NotSeekable))?,
sample,
)?;
self.consumed = 0;
while sample > pos {
let buf = self.fill_buf()?;
match buf[0].len() {
0 => {
return Err(Error::InvalidSeek);
}
buf_samples => {
let to_consume = buf_samples.min((sample - pos).try_into().unwrap());
self.consume(to_consume);
pos += to_consume as u64;
}
}
}
Ok(())
}
}
impl<R: std::io::Read> Metadata for FlacChannelReader<R> {
#[inline]
fn channel_count(&self) -> u8 {
self.decoder.channel_count().get()
}
#[inline]
fn channel_mask(&self) -> ChannelMask {
self.decoder.channel_mask()
}
#[inline]
fn sample_rate(&self) -> u32 {
self.decoder.sample_rate()
}
#[inline]
fn bits_per_sample(&self) -> u32 {
self.decoder.bits_per_sample()
}
#[inline]
fn total_samples(&self) -> Option<u64> {
self.decoder.total_samples().map(|s| s.get())
}
#[inline]
fn md5(&self) -> Option<&[u8; 16]> {
self.decoder.md5()
}
}
pub struct FlacStreamReader<R> {
reader: R,
buf: Frame,
samples: Vec<i32>,
}
impl<R: std::io::BufRead> FlacStreamReader<R> {
#[inline]
pub fn new(reader: R) -> Self {
Self {
reader,
buf: Frame::default(),
samples: Vec::default(),
}
}
pub fn read(&mut self) -> Result<FrameBuf<'_>, Error> {
use crate::crc::{Checksum, Crc16, CrcReader};
use crate::stream::FrameHeader;
use bitstream_io::{BigEndian, BitReader};
use std::io::Read;
let (header, mut crc16_reader) = loop {
self.reader.skip_until(0b11111111)?;
match self.reader.fill_buf() {
Ok([]) => {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"eof looking for frame sync",
)
.into());
}
Ok([byte, ..]) if byte >> 1 == 0b1111100 => {
let mut crc_reader: CrcReader<_, Crc16> = CrcReader::new(
std::slice::from_ref(&0b11111111).chain(self.reader.by_ref()),
);
if let Ok(header) = FrameHeader::read_subset(&mut crc_reader) {
break (header, crc_reader);
}
}
Ok(_) => continue,
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
Err(e) => return Err(e.into()),
}
};
read_subframes(
BitReader::endian(crc16_reader.by_ref(), BigEndian),
&header,
&mut self.buf,
)?;
if crc16_reader.into_checksum().valid() {
self.samples.clear();
self.samples.extend(self.buf.iter());
Ok(FrameBuf {
samples: self.samples.as_slice(),
sample_rate: header.sample_rate.into(),
channels: header.channel_assignment.count(),
bits_per_sample: header.bits_per_sample.into(),
})
} else {
Err(Error::Crc16Mismatch)
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct FrameBuf<'s> {
pub samples: &'s [i32],
pub sample_rate: u32,
pub channels: u8,
pub bits_per_sample: u32,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub enum Verified {
MD5Match,
MD5Mismatch,
NoMD5,
}
pub fn verify<P: AsRef<Path>>(p: P) -> Result<Verified, Error> {
File::open(p.as_ref())
.map_err(Error::Io)
.and_then(|r| verify_reader(BufReader::new(r)))
}
pub fn verify_reader<R: std::io::Read>(r: R) -> Result<Verified, Error> {
use crate::byteorder::LittleEndian;
let mut r = FlacByteReader::endian(r, LittleEndian)?;
match r.md5().cloned() {
Some(flac_md5) => {
let mut output_md5 = md5::Context::new();
std::io::copy(&mut r, &mut output_md5)?;
Ok(if flac_md5 == output_md5.finalize().0 {
Verified::MD5Match
} else {
Verified::MD5Mismatch
})
}
None => std::io::copy(&mut r, &mut std::io::sink())
.map(|_| Verified::NoMD5)
.map_err(Error::Io),
}
}
#[derive(Clone)]
struct Decoder<R> {
reader: R,
blocks: BlockList,
current_sample: u64,
buf: Frame,
}
impl<R: std::io::Read> Decoder<R> {
fn new(reader: R, blocks: BlockList) -> Self {
Self {
reader,
blocks,
current_sample: 0,
buf: Frame::default(),
}
}
fn channel_count(&self) -> NonZero<u8> {
self.blocks.streaminfo().channels
}
fn channel_mask(&self) -> ChannelMask {
self.blocks.channel_mask()
}
fn sample_rate(&self) -> u32 {
self.blocks.streaminfo().sample_rate
}
fn bits_per_sample(&self) -> u32 {
self.blocks.streaminfo().bits_per_sample.into()
}
fn total_samples(&self) -> Option<NonZero<u64>> {
self.blocks.streaminfo().total_samples
}
fn md5(&self) -> Option<&[u8; 16]> {
self.blocks.streaminfo().md5.as_ref()
}
fn metadata(&self) -> &BlockList {
&self.blocks
}
fn read_frame(&mut self) -> Result<Option<&Frame>, Error> {
use crate::crc::{Checksum, Crc16, CrcReader};
use crate::stream::FrameHeader;
use bitstream_io::{BigEndian, BitReader};
use std::io::Read;
let mut crc16_reader: CrcReader<_, Crc16> = CrcReader::new(self.reader.by_ref());
let header = match self
.blocks
.streaminfo()
.total_samples
.map(|total| total.get() - self.current_sample)
{
Some(0) => return Ok(None),
Some(remaining) => FrameHeader::read(crc16_reader.by_ref(), self.blocks.streaminfo())
.and_then(|header| {
let block_size = u16::from(header.block_size);
(u64::from(block_size) == remaining || block_size > 14)
.then_some(header)
.ok_or(Error::ShortBlock)
})?,
None => match FrameHeader::read(crc16_reader.by_ref(), self.blocks.streaminfo()) {
Ok(header) => header,
Err(Error::Io(err)) if err.kind() == std::io::ErrorKind::UnexpectedEof => {
return Ok(None);
}
Err(err) => return Err(err),
},
};
read_subframes(
BitReader::endian(crc16_reader.by_ref(), BigEndian),
&header,
&mut self.buf,
)?;
if !crc16_reader.into_checksum().valid() {
return Err(Error::Crc16Mismatch);
}
self.current_sample += u64::from(u16::from(header.block_size));
Ok(Some(&self.buf))
}
}
impl<R: std::io::Seek> Decoder<R> {
fn seek(&mut self, frames_start: u64, sample: u64) -> Result<u64, Error> {
use crate::metadata::SeekPoint;
use std::io::SeekFrom;
match self.blocks.get() {
Some(SeekTable { points: seektable }) => {
match seektable.iter().rfind(|point| {
point
.sample_offset()
.map(|offset| offset <= sample)
.unwrap_or(false)
}) {
Some(SeekPoint::Defined {
sample_offset,
byte_offset,
..
}) => {
assert!(*sample_offset <= sample);
self.reader
.seek(SeekFrom::Start(frames_start + byte_offset))?;
self.current_sample = *sample_offset;
Ok(*sample_offset)
}
_ => {
self.reader.seek(SeekFrom::Start(frames_start))?;
self.current_sample = 0;
Ok(0)
}
}
}
None => {
self.reader.seek(SeekFrom::Start(frames_start))?;
self.current_sample = 0;
Ok(0)
}
}
}
}
fn read_subframes<R: BitRead>(
mut reader: R,
header: &crate::stream::FrameHeader,
buf: &mut Frame,
) -> Result<(), Error> {
use crate::stream::ChannelAssignment;
match header.channel_assignment {
ChannelAssignment::Independent(total_channels) => {
buf.resized_channels(
header.bits_per_sample.into(),
total_channels.into(),
u16::from(header.block_size).into(),
)
.try_for_each(|channel| {
read_subframe(&mut reader, header.bits_per_sample.into(), channel)
})?;
}
ChannelAssignment::LeftSide => {
let (left, side) = buf.resized_stereo(
header.bits_per_sample.into(),
u16::from(header.block_size).into(),
);
read_subframe(&mut reader, header.bits_per_sample.into(), left)?;
match header.bits_per_sample.checked_add(1) {
Some(side_bps) => {
read_subframe(&mut reader, side_bps, side)?;
left.iter().zip(side.iter_mut()).for_each(|(left, side)| {
*side = *left - *side;
});
}
None => {
let mut side_i64 = vec![0; side.len()];
read_subframe::<33, R, i64>(
&mut reader,
SignedBitCount::from(header.bits_per_sample)
.checked_add(1)
.expect("excessive bps for substream"),
&mut side_i64,
)?;
left.iter().zip(side_i64).zip(side.iter_mut()).for_each(
|((left, side_i64), side)| {
*side = (*left as i64 - side_i64) as i32;
},
);
}
}
}
ChannelAssignment::SideRight => {
let (side, right) = buf.resized_stereo(
header.bits_per_sample.into(),
u16::from(header.block_size).into(),
);
match header.bits_per_sample.checked_add(1) {
Some(side_bps) => {
read_subframe(&mut reader, side_bps, side)?;
read_subframe(&mut reader, header.bits_per_sample.into(), right)?;
side.iter_mut().zip(right.iter()).for_each(|(side, right)| {
*side += *right;
});
}
None => {
let mut side_i64 = vec![0; side.len()];
read_subframe::<33, R, i64>(
&mut reader,
SignedBitCount::from(header.bits_per_sample)
.checked_add(1)
.expect("excessive bps for substream"),
&mut side_i64,
)?;
read_subframe(&mut reader, header.bits_per_sample.into(), right)?;
side.iter_mut().zip(side_i64).zip(right.iter()).for_each(
|((side, side_64), right)| {
*side = (side_64 + *right as i64) as i32;
},
);
}
}
}
ChannelAssignment::MidSide => {
let (mid, side) = buf.resized_stereo(
header.bits_per_sample.into(),
u16::from(header.block_size).into(),
);
read_subframe(&mut reader, header.bits_per_sample.into(), mid)?;
match header.bits_per_sample.checked_add(1) {
Some(side_bps) => {
read_subframe(&mut reader, side_bps, side)?;
mid.iter_mut().zip(side.iter_mut()).for_each(|(mid, side)| {
let sum = *mid * 2 + side.abs() % 2;
*mid = (sum + *side) >> 1;
*side = (sum - *side) >> 1;
});
}
None => {
let mut side_i64 = vec![0; side.len()];
read_subframe::<33, R, i64>(
&mut reader,
SignedBitCount::from(header.bits_per_sample)
.checked_add(1)
.expect("excessive bps for substream"),
&mut side_i64,
)?;
mid.iter_mut().zip(side.iter_mut()).zip(side_i64).for_each(
|((mid, side), side_i64)| {
let sum = *mid as i64 * 2 + (side_i64.abs() % 2);
*mid = ((sum + side_i64) >> 1) as i32;
*side = ((sum - side_i64) >> 1) as i32;
},
);
}
}
}
}
reader.byte_align();
reader.skip(16)?;
Ok(())
}
fn read_subframe<const MAX: u32, R: BitRead, I: SignedInteger>(
reader: &mut R,
bits_per_sample: SignedBitCount<MAX>,
channel: &mut [I],
) -> Result<(), Error> {
use crate::stream::{SubframeHeader, SubframeHeaderType};
let header = reader.parse::<SubframeHeader>()?;
let effective_bps = bits_per_sample
.checked_sub::<MAX>(header.wasted_bps)
.ok_or(Error::ExcessiveWastedBits)?;
match header.type_ {
SubframeHeaderType::Constant => {
channel.fill(reader.read_signed_counted(effective_bps)?);
}
SubframeHeaderType::Verbatim => {
channel.iter_mut().try_for_each(|i| {
*i = reader.read_signed_counted(effective_bps)?;
Ok::<(), Error>(())
})?;
}
SubframeHeaderType::Fixed { order } => {
read_fixed_subframe(
reader,
effective_bps,
SubframeHeaderType::FIXED_COEFFS[order as usize],
channel,
)?;
}
SubframeHeaderType::Lpc { order } => {
read_lpc_subframe(reader, effective_bps, order, channel)?;
}
}
if header.wasted_bps > 0 {
channel.iter_mut().for_each(|i| *i <<= header.wasted_bps);
}
Ok(())
}
fn read_fixed_subframe<const MAX: u32, R: BitRead, I: SignedInteger>(
reader: &mut R,
bits_per_sample: SignedBitCount<MAX>,
coefficients: &[i64],
channel: &mut [I],
) -> Result<(), Error> {
let (warm_up, residuals) = channel
.split_at_mut_checked(coefficients.len())
.ok_or(Error::InvalidFixedOrder)?;
warm_up.iter_mut().try_for_each(|s| {
*s = reader.read_signed_counted(bits_per_sample)?;
Ok::<_, std::io::Error>(())
})?;
read_residuals(reader, coefficients.len(), residuals)?;
predict(coefficients, 0, channel);
Ok(())
}
fn read_lpc_subframe<const MAX: u32, R: BitRead, I: SignedInteger>(
reader: &mut R,
bits_per_sample: SignedBitCount<MAX>,
predictor_order: NonZero<u8>,
channel: &mut [I],
) -> Result<(), Error> {
let mut coefficients: [i64; 32] = [0; 32];
let (warm_up, residuals) = channel
.split_at_mut_checked(predictor_order.get().into())
.ok_or(Error::InvalidLpcOrder)?;
warm_up.iter_mut().try_for_each(|s| {
*s = reader.read_signed_counted(bits_per_sample)?;
Ok::<_, std::io::Error>(())
})?;
let qlp_precision: SignedBitCount<15> = reader
.read_count::<0b1111>()?
.checked_add(1)
.and_then(|c| c.signed_count())
.ok_or(Error::InvalidQlpPrecision)?;
let qlp_shift: u32 = reader
.read::<5, i32>()?
.try_into()
.map_err(|_| Error::NegativeLpcShift)?;
let coefficients = &mut coefficients[0..predictor_order.get().into()];
coefficients.iter_mut().try_for_each(|c| {
*c = reader.read_signed_counted(qlp_precision)?;
Ok::<_, std::io::Error>(())
})?;
read_residuals(reader, coefficients.len(), residuals)?;
predict(coefficients, qlp_shift, channel);
Ok(())
}
fn predict<I: SignedInteger>(coefficients: &[i64], qlp_shift: u32, channel: &mut [I]) {
for split in coefficients.len()..channel.len() {
let (predicted, residuals) = channel.split_at_mut(split);
residuals[0] += I::from_i64(
predicted
.iter()
.rev()
.zip(coefficients)
.map(|(x, y)| (*x).into() * y)
.sum::<i64>()
>> qlp_shift,
);
}
}
#[test]
fn verify_prediction() {
let mut coefficients = [-75, 166, 121, -269, -75, -399, 1042];
let mut buffer = [
-796, -547, -285, -32, 199, 443, 670, -2, -23, 14, 6, 3, -4, 12, -2, 10,
];
coefficients.reverse();
predict(&coefficients, 9, &mut buffer);
assert_eq!(
&buffer,
&[
-796, -547, -285, -32, 199, 443, 670, 875, 1046, 1208, 1343, 1454, 1541, 1616, 1663,
1701
]
);
let mut coefficients = [119, -255, 555, -836, 879, -1199, 1757];
let mut buffer = [-21363, -21951, -22649, -24364, -27297, -26870, -30017, 3157];
coefficients.reverse();
predict(&coefficients, 10, &mut buffer);
assert_eq!(
&buffer,
&[
-21363, -21951, -22649, -24364, -27297, -26870, -30017, -29718
]
);
let mut coefficients = [
709, -2589, 4600, -4612, 1350, 4220, -9743, 12671, -12129, 8586, -3775, -645, 3904, -5543,
4373, 182, -6873, 13265, -15417, 11550,
];
let mut buffer = [
213238, 210830, 234493, 209515, 235139, 201836, 208151, 186277, 157720, 148176, 115037,
104836, 60794, 54523, 412, 17943, -6025, -3713, 8373, 11764, 30094,
];
coefficients.reverse();
predict(&coefficients, 12, &mut buffer);
assert_eq!(
&buffer,
&[
213238, 210830, 234493, 209515, 235139, 201836, 208151, 186277, 157720, 148176, 115037,
104836, 60794, 54523, 412, 17943, -6025, -3713, 8373, 11764, 33931,
]
);
}
fn read_residuals<R: BitRead, I: SignedInteger>(
reader: &mut R,
predictor_order: usize,
residuals: &mut [I],
) -> Result<(), Error> {
fn read_block<const RICE_MAX: u32, R: BitRead, I: SignedInteger>(
reader: &mut R,
predictor_order: usize,
residuals: &mut [I],
) -> Result<(), Error> {
use crate::stream::ResidualPartitionHeader;
let block_size = predictor_order + residuals.len();
let partition_order = reader.read::<4, u32>()?;
let partition_count = 1 << partition_order;
let partitions = residuals.rchunks_mut(block_size / partition_count).rev();
if partitions.len() != partition_count {
return Err(Error::InvalidPartitionOrder);
}
for partition in partitions {
match reader.parse()? {
ResidualPartitionHeader::Standard { rice } => {
partition.iter_mut().try_for_each(|s| {
let msb = reader.read_unary::<1>()?;
let lsb = reader.read_counted::<RICE_MAX, u32>(rice)?;
let unsigned = (msb << u32::from(rice)) | lsb;
*s = if (unsigned & 1) == 1 {
-(I::from_u32(unsigned >> 1)) - I::ONE
} else {
I::from_u32(unsigned >> 1)
};
Ok::<(), std::io::Error>(())
})?;
}
ResidualPartitionHeader::Escaped { escape_size } => {
partition.iter_mut().try_for_each(|s| {
*s = reader.read_signed_counted(escape_size)?;
Ok::<(), std::io::Error>(())
})?;
}
ResidualPartitionHeader::Constant => {
partition.fill(I::ZERO);
}
}
}
Ok(())
}
match reader.read::<2, u8>()? {
0 => read_block::<0b1111, R, I>(reader, predictor_order, residuals),
1 => read_block::<0b11111, R, I>(reader, predictor_order, residuals),
_ => Err(Error::InvalidCodingMethod),
}
}