use std::cmp::max;
use std::cmp::min;
#[cfg(feature = "serde")]
use serde::Deserialize;
#[cfg(feature = "serde")]
use serde::Serialize;
use super::bitrepr::BitRepr;
use super::verify::verify_block_size;
use super::verify::verify_bps;
use super::verify::verify_sample_range;
use crate::arrayutils::find_max;
use crate::arrayutils::wrapping_sum;
use crate::bitsink::BitSink;
use crate::bitsink::MemSink;
use crate::constant::panic_msg;
use crate::constant::qlpc::MAX_ORDER as MAX_LPC_ORDER;
use crate::constant::MAX_CHANNELS;
use crate::error::verify_range;
use crate::error::verify_true;
use crate::error::Verify;
use crate::error::VerifyError;
use crate::rice;
import_simd!(as simd);
#[cfg(feature = "serde")]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(remote = "simd::Simd"))]
struct SimdDef<T, const N: usize>(#[serde(getter = "simd::Simd::as_array")] [T; N])
where
T: simd::SimdElement,
simd::LaneCount<N>: simd::SupportedLaneCount,
[T; N]: for<'a> Deserialize<'a> + Serialize;
#[cfg(feature = "serde")]
impl<T, const N: usize> From<SimdDef<T, N>> for simd::Simd<T, N>
where
T: simd::SimdElement,
simd::LaneCount<N>: simd::SupportedLaneCount,
[T; N]: for<'a> Deserialize<'a> + Serialize,
{
fn from(def: SimdDef<T, N>) -> Self {
Self::from_array(def.0)
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Stream {
#[allow(clippy::struct_field_names)] stream_info: MetadataBlock,
metadata: Vec<MetadataBlock>,
frames: Vec<Frame>,
}
impl Stream {
pub fn new(
sample_rate: usize,
channels: usize,
bits_per_sample: usize,
) -> Result<Self, VerifyError> {
Ok(Self::with_stream_info(StreamInfo::new(
sample_rate,
channels,
bits_per_sample,
)?))
}
pub fn with_stream_info(stream_info: StreamInfo) -> Self {
Self {
stream_info: MetadataBlock::from_stream_info(stream_info, true),
metadata: vec![],
frames: vec![],
}
}
pub fn stream_info(&self) -> &StreamInfo {
if let MetadataBlockData::StreamInfo(ref info) = self.stream_info.data {
info
} else {
panic!("Stream is not properly initialized.")
}
}
pub(crate) fn stream_info_block(&self) -> &MetadataBlock {
&self.stream_info
}
pub fn stream_info_mut(&mut self) -> &mut StreamInfo {
if let MetadataBlockData::StreamInfo(ref mut info) = self.stream_info.data {
info
} else {
panic!("Stream is not properly initialized.")
}
}
pub fn add_frame(&mut self, frame: Frame) {
self.stream_info_mut().update_frame_info(&frame);
self.frames.push(frame);
}
pub fn add_metadata_block(&mut self, metadata: MetadataBlockData) {
let metadata = MetadataBlock::from_parts(true, metadata);
if let Some(x) = self.metadata.last_mut() {
x.is_last = false;
} else {
self.stream_info.is_last = false;
}
self.metadata.push(metadata);
}
pub fn frame(&self, n: usize) -> Option<&Frame> {
self.frames.get(n)
}
pub fn frame_count(&self) -> usize {
self.frames.len()
}
pub(crate) fn metadata(&self) -> &[MetadataBlock] {
&self.metadata
}
#[allow(dead_code)]
pub(crate) fn frames(&self) -> &[Frame] {
&self.frames
}
pub(crate) fn verify_variable_blocking_frames(&self) -> Result<(), VerifyError> {
let mut current = 0u64;
for (i, frame) in self.frames.iter().enumerate() {
verify_true!(
"variable_block_size",
frame.header.variable_block_size,
"must be same for all frames"
)
.and_then(|()| {
verify_true!(
"start_sample_number",
frame.header.start_sample_number == current,
"must be the sum of the block sizes of the preceding frames"
)
})
.map_err(|e| e.within("header").within(&format!("frames[{i}]")))?;
frame
.verify()
.map_err(|e| e.within(&format!("frames[{i}]")))?;
current = current.wrapping_add(frame.header.block_size() as u64);
}
Ok(())
}
pub(crate) fn verify_fixed_blocking_frames(&self) -> Result<(), VerifyError> {
let mut current = 0u32;
for (i, frame) in self.frames.iter().enumerate() {
verify_true!(
"variable_block_size",
!frame.header.variable_block_size,
"must be same for all frames"
)
.and_then(|()| {
verify_true!(
"frame_number",
frame.header.frame_number == current,
"must be the count of the preceding frames"
)
})
.map_err(|e| e.within("header").within(&format!("frames[{i}]")))?;
frame
.verify()
.map_err(|e| e.within(&format!("frames[{i}]")))?;
current = current.wrapping_add(1);
}
Ok(())
}
#[cfg(any(test, feature = "decode"))]
pub(crate) fn frames_mut(&mut self) -> &mut Vec<Frame> {
&mut self.frames
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MetadataBlock {
pub(crate) is_last: bool,
pub(crate) data: MetadataBlockData,
}
impl MetadataBlock {
pub(crate) const fn from_parts(is_last: bool, data: MetadataBlockData) -> Self {
Self { is_last, data }
}
const fn from_stream_info(info: StreamInfo, is_last: bool) -> Self {
Self {
is_last,
data: MetadataBlockData::StreamInfo(info),
}
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", content = "data"))]
#[non_exhaustive]
pub enum MetadataBlockData {
StreamInfo(StreamInfo),
Unknown {
typetag: u8,
data: Vec<u8>,
},
}
impl MetadataBlockData {
pub fn new_unknown(tag: u8, data: &[u8]) -> Result<Self, VerifyError> {
verify_range!("tag", tag, 0..=126)?;
Ok(Self::Unknown {
typetag: tag,
data: data.to_owned(),
})
}
pub(crate) fn typetag(&self) -> u8 {
match self {
Self::StreamInfo(_) => 0,
Self::Unknown { typetag, .. } => *typetag,
}
}
pub fn as_stream_info(&self) -> Option<&StreamInfo> {
if let Self::StreamInfo(ref info) = self {
Some(info)
} else {
None
}
}
}
impl From<StreamInfo> for MetadataBlockData {
fn from(value: StreamInfo) -> Self {
Self::StreamInfo(value)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct StreamInfo {
min_block_size: u16, max_block_size: u16, min_frame_size: u32, max_frame_size: u32, sample_rate: u32, channels: u8, bits_per_sample: u8, total_samples: u64, md5: [u8; 16],
}
impl StreamInfo {
pub fn new(
sample_rate: usize,
channels: usize,
bits_per_sample: usize,
) -> Result<Self, VerifyError> {
let ret = Self {
min_block_size: u16::MAX,
max_block_size: 0,
min_frame_size: u32::MAX,
max_frame_size: 0,
sample_rate: sample_rate as u32,
channels: channels as u8,
bits_per_sample: bits_per_sample as u8,
total_samples: 0,
md5: [0; 16],
};
ret.verify()?;
Ok(ret)
}
pub fn update_frame_info(&mut self, frame: &Frame) {
let block_size = frame.block_size() as u16;
self.min_block_size = min(block_size, self.min_block_size);
self.max_block_size = max(block_size, self.max_block_size);
let frame_size_in_bytes = (frame.count_bits() / 8) as u32;
self.min_frame_size = min(frame_size_in_bytes, self.min_frame_size);
self.max_frame_size = max(frame_size_in_bytes, self.max_frame_size);
self.total_samples += u64::from(block_size);
}
#[inline]
pub fn min_frame_size(&self) -> usize {
self.min_frame_size as usize
}
#[inline]
pub fn max_frame_size(&self) -> usize {
self.max_frame_size as usize
}
#[inline]
pub fn min_block_size(&self) -> usize {
self.min_block_size as usize
}
#[inline]
pub fn max_block_size(&self) -> usize {
self.max_block_size as usize
}
#[inline]
pub fn sample_rate(&self) -> usize {
self.sample_rate as usize
}
#[inline]
pub fn channels(&self) -> usize {
self.channels as usize
}
#[inline]
pub fn bits_per_sample(&self) -> usize {
self.bits_per_sample as usize
}
#[inline]
pub fn total_samples(&self) -> usize {
self.total_samples as usize
}
#[inline]
pub fn set_total_samples(&mut self, n: usize) {
self.total_samples = n as u64;
}
#[inline]
pub fn md5_digest(&self) -> &[u8; 16] {
&self.md5
}
pub fn set_md5_digest(&mut self, digest: &[u8; 16]) {
self.md5.copy_from_slice(digest);
}
pub fn set_block_sizes(
&mut self,
min_value: usize,
max_value: usize,
) -> Result<(), VerifyError> {
self.min_block_size = min_value
.try_into()
.map_err(|_| VerifyError::new("min_block_size", "must be a valid block size."))?;
self.max_block_size = max_value
.try_into()
.map_err(|_| VerifyError::new("max_block_size", "must be a valid block size."))?;
verify_block_size!("min_block_size", self.min_block_size as usize)?;
verify_block_size!("max_block_size", self.max_block_size as usize)?;
verify_true!(
"min_block_size",
self.min_block_size <= self.max_block_size,
"must be smaller than `max_block_size`"
)?;
Ok(())
}
pub fn set_frame_sizes(
&mut self,
min_value: usize,
max_value: usize,
) -> Result<(), VerifyError> {
self.min_frame_size = min_value
.try_into()
.map_err(|_| VerifyError::new("min_frame_size", "must be a 32-bit integer."))?;
self.max_frame_size = max_value
.try_into()
.map_err(|_| VerifyError::new("min_frame_size", "must be a 32-bit integer."))?;
verify_true!(
"min_frame_size",
self.min_frame_size <= self.max_frame_size,
"must be smaller than `max_frame_size`"
)?;
Ok(())
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Frame {
header: FrameHeader,
subframes: Vec<SubFrame>,
precomputed_bitstream: Option<Vec<u8>>,
}
impl Frame {
pub(crate) fn new_empty(
block_size_spec: BlockSizeSpec,
ch_info: ChannelAssignment,
sample_size_spec: SampleSizeSpec,
sample_rate_spec: SampleRateSpec,
) -> Self {
let header =
FrameHeader::from_specs(block_size_spec, ch_info, sample_size_spec, sample_rate_spec);
Self {
header,
subframes: Vec::with_capacity(MAX_CHANNELS),
precomputed_bitstream: None,
}
}
pub fn new<I>(header: FrameHeader, subframes: I) -> Result<Self, VerifyError>
where
I: Iterator<Item = SubFrame>,
{
let subframes: Vec<SubFrame> = subframes.collect();
verify_true!(
"subframes.len()",
header.channel_assignment().channels() == subframes.len(),
"must match to the channel specification in the header"
)?;
Ok(Self::from_parts(header, subframes))
}
#[inline]
pub(crate) fn from_parts(header: FrameHeader, subframes: Vec<SubFrame>) -> Self {
Self {
header,
subframes,
precomputed_bitstream: None,
}
}
#[inline]
pub fn into_parts(self) -> (FrameHeader, Vec<SubFrame>) {
(self.header, self.subframes)
}
#[inline]
pub(crate) fn add_subframe(&mut self, subframe: SubFrame) {
self.precomputed_bitstream = None;
self.subframes.push(subframe);
assert!(self.subframes.len() <= MAX_CHANNELS);
}
#[inline]
pub fn header(&self) -> &FrameHeader {
&self.header
}
#[inline]
pub(crate) fn header_mut(&mut self) -> &mut FrameHeader {
&mut self.header
}
#[inline]
pub fn subframe(&self, ch: usize) -> Option<&SubFrame> {
self.subframes.get(ch)
}
#[inline]
pub fn subframe_count(&self) -> usize {
self.subframes.len()
}
#[inline]
pub(crate) fn subframes(&self) -> &[SubFrame] {
&self.subframes
}
#[inline]
pub fn block_size(&self) -> usize {
self.header.block_size()
}
pub fn precompute_bitstream(&mut self) {
if self.precomputed_bitstream.is_some() {
return;
}
let mut dest = MemSink::<u8>::with_capacity(self.count_bits());
if self.write(&mut dest).is_ok() {
self.precomputed_bitstream = Some(dest.into_inner());
}
}
#[inline]
pub(crate) fn precomputed_bitstream(&self) -> Option<&Vec<u8>> {
self.precomputed_bitstream.as_ref()
}
#[inline]
pub fn into_stereo_channels(self) -> Result<(FrameHeader, SubFrame, SubFrame), Self> {
if self.subframe_count() != 2 {
return Err(self);
}
let (header, subframes) = self.into_parts();
let mut iter = subframes.into_iter();
let ch0 = iter.next().expect(panic_msg::DATA_INCONSISTENT);
let ch1 = iter.next().expect(panic_msg::DATA_INCONSISTENT);
Ok((header, ch0, ch1))
}
#[cfg(test)]
#[inline]
pub(crate) const fn is_bitstream_precomputed(&self) -> bool {
self.precomputed_bitstream.is_some()
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", content = "data"))]
pub enum ChannelAssignment {
Independent(u8),
LeftSide,
RightSide,
MidSide,
}
impl ChannelAssignment {
#[inline]
pub const fn from_tag(tag: u8) -> Option<Self> {
if tag < 8 {
Some(Self::Independent(tag + 1))
} else if tag == 8 {
Some(Self::LeftSide)
} else if tag == 9 {
Some(Self::RightSide)
} else if tag == 10 {
Some(Self::MidSide)
} else {
None
}
}
#[inline]
pub const fn bits_per_sample_offset(&self, ch: usize) -> usize {
#[allow(clippy::match_same_arms, clippy::bool_to_int_with_if)]
match *self {
Self::Independent(_) => 0,
Self::LeftSide => {
if ch == 1 {
1 } else {
0 }
}
Self::RightSide => {
if ch == 0 {
1 } else {
0 }
}
Self::MidSide => {
if ch == 1 {
1 } else {
0 }
}
}
}
#[inline]
pub(crate) fn select_channels(
&self,
l: SubFrame,
r: SubFrame,
m: SubFrame,
s: SubFrame,
) -> (SubFrame, SubFrame) {
match *self {
Self::Independent(_) => (l, r),
Self::LeftSide => (l, s),
Self::RightSide => (s, r),
Self::MidSide => (m, s),
}
}
#[inline]
pub(crate) fn channels(&self) -> usize {
if let Self::Independent(n) = self {
*n as usize
} else {
2
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FrameOffset {
Frame(u32),
StartSample(u64),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type"))]
pub enum BlockSizeSpec {
#[allow(dead_code)]
Reserved,
S192,
Pow2Mul576(u8),
ExtraByte(u8),
ExtraTwoBytes(u16),
Pow2Mul256(u8),
}
impl BlockSizeSpec {
#[inline]
pub fn from_size(size: u16) -> Self {
match size {
192 => Self::S192,
576 | 1152 | 2304 | 4608 => Self::Pow2Mul576(u32::from(size / 576).ilog2() as u8),
256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | 32768 => {
Self::Pow2Mul256(u32::from(size / 256).ilog2() as u8)
}
x if x <= 256 => Self::ExtraByte((x - 1) as u8),
x => Self::ExtraTwoBytes(x - 1),
}
}
#[inline]
pub(crate) fn count_extra_bits(self) -> usize {
match self {
Self::ExtraByte(_) => 8,
Self::ExtraTwoBytes(_) => 16,
Self::Reserved | Self::S192 | Self::Pow2Mul576(_) | Self::Pow2Mul256(_) => 0,
}
}
#[inline]
pub fn block_size(self) -> Option<usize> {
match self {
Self::Reserved => None,
Self::S192 => Some(192),
Self::Pow2Mul576(x) => Some(576usize * (1usize << x as usize)),
Self::ExtraByte(x) => Some((x + 1) as usize),
Self::ExtraTwoBytes(x) => Some((x + 1) as usize),
Self::Pow2Mul256(x) => Some(256usize * (1usize << x as usize)),
}
}
#[inline]
pub(crate) fn tag(self) -> u8 {
match self {
Self::Reserved => 0,
Self::S192 => 1,
Self::Pow2Mul576(x) => 2 + x,
Self::ExtraByte(_) => 6,
Self::ExtraTwoBytes(_) => 7,
Self::Pow2Mul256(x) => 8 + x,
}
}
#[inline]
pub(crate) fn write_extra_bits<S: BitSink>(self, dest: &mut S) -> Result<(), S::Error> {
match self {
Self::ExtraByte(v) => dest.write_lsbs(v, 8),
Self::ExtraTwoBytes(v) => dest.write_lsbs(v, 16),
Self::Reserved | Self::S192 | Self::Pow2Mul576(_) | Self::Pow2Mul256(_) => Ok(()),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type"))]
pub enum SampleSizeSpec {
Unspecified = 0,
B8 = 1,
B12 = 2,
Reserved = 3,
B16 = 4,
B20 = 5,
B24 = 6,
B32 = 7,
}
impl SampleSizeSpec {
#[inline]
#[allow(dead_code)]
pub const fn from_tag(value: u8) -> Option<Self> {
match value {
0 => Some(Self::Unspecified),
1 => Some(Self::B8),
2 => Some(Self::B12),
3 => Some(Self::Reserved),
4 => Some(Self::B16),
5 => Some(Self::B20),
6 => Some(Self::B24),
7 => Some(Self::B32),
_ => None,
}
}
#[inline]
pub const fn into_tag(self) -> u8 {
self as u8
}
#[inline]
pub const fn from_bits(bits: u8) -> Option<Self> {
match bits {
8 => Some(Self::B8),
12 => Some(Self::B12),
16 => Some(Self::B16),
20 => Some(Self::B20),
24 => Some(Self::B24),
32 => Some(Self::B32),
_ => None,
}
}
#[inline]
pub const fn into_bits(self) -> Option<u8> {
match self {
Self::Unspecified | Self::Reserved => None,
Self::B8 => Some(8),
Self::B12 => Some(12),
Self::B16 => Some(16),
Self::B20 => Some(20),
Self::B24 => Some(24),
Self::B32 => Some(32),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type"))]
pub enum SampleRateSpec {
Unspecified,
R88_2kHz,
R176_4kHz,
R192kHz,
R8kHz,
R16kHz,
R22_05kHz,
R24kHz,
R32kHz,
R44_1kHz,
R48kHz,
R96kHz,
KHz(u8),
Hz(u16),
DaHz(u16),
}
impl SampleRateSpec {
#[inline]
pub fn from_freq(freq: u32) -> Option<Self> {
match freq {
88_200 => Some(Self::R88_2kHz),
176_400 => Some(Self::R176_4kHz),
192_000 => Some(Self::R192kHz),
8_000 => Some(Self::R8kHz),
16_000 => Some(Self::R16kHz),
22_050 => Some(Self::R22_05kHz),
24_000 => Some(Self::R24kHz),
32_000 => Some(Self::R32kHz),
44_100 => Some(Self::R44_1kHz),
48_000 => Some(Self::R48kHz),
96_000 => Some(Self::R96kHz),
_ => None,
}
.or_else(|| {
(0 == freq % 1000)
.then(|| (freq / 1000).try_into().ok().map(Self::KHz))
.flatten()
})
.or_else(|| {
(0 == freq % 10)
.then(|| (freq / 10).try_into().ok().map(Self::DaHz))
.flatten()
})
.or_else(|| freq.try_into().ok().map(Self::Hz))
}
#[cfg(any(test, feature = "decode"))]
#[inline]
pub(crate) fn from_tag_and_data(tag: u8, value: Option<usize>) -> Option<Self> {
if tag > 0b1110 {
return None;
}
Some(match tag {
0b0000 => Self::Unspecified,
0b0001 => Self::R88_2kHz,
0b0010 => Self::R176_4kHz,
0b0011 => Self::R192kHz,
0b0100 => Self::R8kHz,
0b0101 => Self::R16kHz,
0b0110 => Self::R22_05kHz,
0b0111 => Self::R24kHz,
0b1000 => Self::R32kHz,
0b1001 => Self::R44_1kHz,
0b1010 => Self::R48kHz,
0b1011 => Self::R96kHz,
0b1100 => Self::KHz(value? as u8),
0b1101 => Self::Hz(value? as u16),
0b1110 => Self::DaHz(value? as u16),
_ => unreachable!(), })
}
#[inline]
pub(crate) fn count_extra_bits(self) -> usize {
match self {
Self::KHz(_) => 8,
Self::DaHz(_) | Self::Hz(_) => 16,
Self::Unspecified
| Self::R88_2kHz
| Self::R176_4kHz
| Self::R192kHz
| Self::R8kHz
| Self::R16kHz
| Self::R22_05kHz
| Self::R24kHz
| Self::R32kHz
| Self::R44_1kHz
| Self::R48kHz
| Self::R96kHz => 0,
}
}
#[inline]
pub(crate) fn tag(self) -> u8 {
match self {
Self::Unspecified => 0,
Self::R88_2kHz => 1,
Self::R176_4kHz => 2,
Self::R192kHz => 3,
Self::R8kHz => 4,
Self::R16kHz => 5,
Self::R22_05kHz => 6,
Self::R24kHz => 7,
Self::R32kHz => 8,
Self::R44_1kHz => 9,
Self::R48kHz => 10,
Self::R96kHz => 11,
Self::KHz(_) => 12,
Self::Hz(_) => 13,
Self::DaHz(_) => 14,
}
}
#[inline]
pub(crate) fn write_extra_bits<S: BitSink>(self, dest: &mut S) -> Result<(), S::Error> {
match self {
Self::KHz(v) => dest.write_lsbs(v, 8),
Self::DaHz(v) | Self::Hz(v) => dest.write_lsbs(v, 16),
Self::Unspecified
| Self::R88_2kHz
| Self::R176_4kHz
| Self::R192kHz
| Self::R8kHz
| Self::R16kHz
| Self::R22_05kHz
| Self::R24kHz
| Self::R32kHz
| Self::R44_1kHz
| Self::R48kHz
| Self::R96kHz => Ok(()),
}
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct FrameHeader {
variable_block_size: bool, block_size_spec: BlockSizeSpec,
channel_assignment: ChannelAssignment,
sample_size_spec: SampleSizeSpec,
sample_rate_spec: SampleRateSpec,
frame_number: u32, start_sample_number: u64, }
impl FrameHeader {
#[inline]
pub(crate) const fn from_specs(
block_size_spec: BlockSizeSpec,
channel_assignment: ChannelAssignment,
sample_size_spec: SampleSizeSpec,
sample_rate_spec: SampleRateSpec,
) -> Self {
Self {
variable_block_size: true,
block_size_spec,
channel_assignment,
sample_size_spec,
sample_rate_spec,
frame_number: 0,
start_sample_number: 0,
}
}
#[inline]
pub fn new(
block_size: usize,
channel_assignment: ChannelAssignment,
bits_per_sample: usize,
sample_rate: usize,
offset: FrameOffset,
) -> Result<Self, VerifyError> {
verify_block_size!("block_size", block_size)?;
let block_size_spec = BlockSizeSpec::from_size(block_size as u16);
let sample_size_spec =
SampleSizeSpec::from_bits(bits_per_sample as u8).ok_or_else(|| {
VerifyError::new("bits_per_sample", "must be one of a supported value.")
})?;
verify_true!(
"bits_per_sample",
sample_size_spec != SampleSizeSpec::B32,
"32-bit encoding is not supported currently."
)?;
channel_assignment.verify()?;
let sample_rate_spec = SampleRateSpec::from_freq(sample_rate as u32)
.ok_or_else(|| VerifyError::new("sample_rate", "must be in a supported range."))?;
let mut ret = Self::from_specs(
block_size_spec,
channel_assignment,
sample_size_spec,
sample_rate_spec,
);
ret.set_frame_offset(offset);
Ok(ret)
}
#[inline]
pub(crate) fn is_variable_blocking(&self) -> bool {
self.variable_block_size
}
#[inline]
pub fn set_frame_offset(&mut self, offset: FrameOffset) {
match offset {
FrameOffset::Frame(n) => self.set_frame_number(n),
FrameOffset::StartSample(n) => self.set_start_sample_number(n),
}
}
#[inline]
fn set_frame_number(&mut self, frame_number: u32) {
self.variable_block_size = false;
self.frame_number = frame_number;
}
#[inline]
fn set_start_sample_number(&mut self, start_sample_number: u64) {
self.variable_block_size = true;
self.start_sample_number = start_sample_number;
}
#[inline]
pub(crate) fn frame_number(&self) -> u32 {
self.frame_number
}
#[inline]
pub(crate) fn start_sample_number(&self) -> u64 {
self.start_sample_number
}
#[inline]
pub(crate) fn sample_rate_spec(&self) -> &SampleRateSpec {
&self.sample_rate_spec
}
#[inline]
pub(crate) fn sample_size_spec(&self) -> &SampleSizeSpec {
&self.sample_size_spec
}
#[inline]
pub(crate) fn reset_channel_assignment(&mut self, channel_assignment: ChannelAssignment) {
self.channel_assignment = channel_assignment;
}
#[inline]
pub fn block_size(&self) -> usize {
self.block_size_spec
.block_size()
.expect("Reserved block-size tag should not be used.")
}
#[inline]
pub(crate) fn block_size_spec(&self) -> BlockSizeSpec {
self.block_size_spec
}
#[inline]
pub fn bits_per_sample(&self) -> Option<usize> {
self.sample_size_spec.into_bits().map(|x| x as usize)
}
#[inline]
pub fn channel_assignment(&self) -> &ChannelAssignment {
&self.channel_assignment
}
}
#[derive(Clone, Debug)]
#[allow(clippy::large_enum_variant)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type"))]
pub enum SubFrame {
Constant(Constant),
Verbatim(Verbatim),
FixedLpc(FixedLpc),
Lpc(Lpc),
}
impl From<Constant> for SubFrame {
fn from(c: Constant) -> Self {
Self::Constant(c)
}
}
impl From<Verbatim> for SubFrame {
fn from(c: Verbatim) -> Self {
Self::Verbatim(c)
}
}
impl From<FixedLpc> for SubFrame {
fn from(c: FixedLpc) -> Self {
Self::FixedLpc(c)
}
}
impl From<Lpc> for SubFrame {
fn from(c: Lpc) -> Self {
Self::Lpc(c)
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Constant {
block_size: usize,
dc_offset: i32,
bits_per_sample: u8,
}
impl Constant {
pub fn new(
block_size: usize,
dc_offset: i32,
bits_per_sample: usize,
) -> Result<Self, VerifyError> {
verify_block_size!("block_size", block_size)?;
verify_bps!("bits_per_sample", bits_per_sample)?;
verify_sample_range!("dc_offset", dc_offset, bits_per_sample)?;
Ok(Self::from_parts(
block_size,
dc_offset,
bits_per_sample as u8,
))
}
#[inline]
pub(crate) fn from_parts(block_size: usize, dc_offset: i32, bits_per_sample: u8) -> Self {
Self {
block_size,
dc_offset,
bits_per_sample,
}
}
#[inline]
pub fn block_size(&self) -> usize {
self.block_size
}
#[inline]
pub fn dc_offset(&self) -> i32 {
self.dc_offset
}
#[inline]
pub fn bits_per_sample(&self) -> usize {
self.bits_per_sample as usize
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Verbatim {
data: Vec<i32>,
bits_per_sample: u8,
}
impl Verbatim {
pub fn new(samples: &[i32], bits_per_sample: usize) -> Result<Self, VerifyError> {
verify_bps!("bits_per_sample", bits_per_sample)?;
for v in samples {
verify_sample_range!("samples", *v, bits_per_sample)?;
}
Ok(Self::from_samples(samples, bits_per_sample as u8))
}
pub(crate) fn from_samples(samples: &[i32], bits_per_sample: u8) -> Self {
Self {
data: Vec::from(samples),
bits_per_sample,
}
}
#[inline]
pub(crate) const fn count_bits_from_metadata(
block_size: usize,
bits_per_sample: usize,
) -> usize {
8 + block_size * bits_per_sample
}
#[inline]
pub fn samples(&self) -> &[i32] {
&self.data
}
#[inline]
pub fn bits_per_sample(&self) -> usize {
self.bits_per_sample as usize
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct FixedLpc {
warm_up: heapless::Vec<i32, 4>,
residual: Residual,
bits_per_sample: u8,
}
impl FixedLpc {
pub fn new(
warm_up: &[i32],
residual: Residual,
bits_per_sample: usize,
) -> Result<Self, VerifyError> {
verify_bps!("bits_per_sample", bits_per_sample)?;
for v in warm_up {
verify_sample_range!("warm_up", *v, bits_per_sample)?;
}
let warm_up = heapless::Vec::from_slice(warm_up)
.map_err(|()| VerifyError::new("warm_up", "must be shorter than (or equal to) 4"))?;
let ret = Self::from_parts(warm_up, residual, bits_per_sample as u8);
Ok(ret)
}
#[inline]
pub(crate) fn from_parts(
warm_up: heapless::Vec<i32, 4>,
residual: Residual,
bits_per_sample: u8,
) -> Self {
Self {
warm_up,
residual,
bits_per_sample,
}
}
#[inline]
pub fn order(&self) -> usize {
self.warm_up.len()
}
#[inline]
pub fn warm_up(&self) -> &[i32] {
&self.warm_up
}
#[inline]
pub fn residual(&self) -> &Residual {
&self.residual
}
#[inline]
pub fn bits_per_sample(&self) -> usize {
self.bits_per_sample as usize
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Lpc {
parameters: QuantizedParameters,
warm_up: heapless::Vec<i32, MAX_LPC_ORDER>,
residual: Residual,
bits_per_sample: u8,
}
impl Lpc {
pub fn new(
warm_up: &[i32],
parameters: QuantizedParameters,
residual: Residual,
bits_per_sample: usize,
) -> Result<Self, VerifyError> {
verify_bps!("bits_per_sample", bits_per_sample)?;
for v in warm_up {
verify_sample_range!("warm_up", *v, bits_per_sample)?;
}
let warm_up = heapless::Vec::from_slice(warm_up).map_err(|()| {
VerifyError::new(
"warm_up",
"must be shorter than (or equal to) `qlpc::MAX_ORDER`",
)
})?;
let ret = Self::from_parts(warm_up, parameters, residual, bits_per_sample as u8);
ret.verify()?;
Ok(ret)
}
#[inline]
pub(crate) fn from_parts(
warm_up: heapless::Vec<i32, MAX_LPC_ORDER>,
parameters: QuantizedParameters,
residual: Residual,
bits_per_sample: u8,
) -> Self {
assert_eq!(warm_up.len(), parameters.order());
Self {
parameters,
warm_up,
residual,
bits_per_sample,
}
}
#[inline]
pub const fn order(&self) -> usize {
self.parameters.order()
}
#[inline]
pub fn warm_up(&self) -> &[i32] {
&self.warm_up
}
#[inline]
pub fn parameters(&self) -> &QuantizedParameters {
&self.parameters
}
#[inline]
pub fn residual(&self) -> &Residual {
&self.residual
}
#[inline]
pub fn bits_per_sample(&self) -> usize {
self.bits_per_sample as usize
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct QuantizedParameters {
#[cfg_attr(feature = "serde", serde(with = "SimdDef"))]
pub(crate) coefs: simd::i16x32,
order: usize,
shift: i8,
precision: usize,
}
#[inline]
fn dequantize_parameter(coef: i16, shift: i8) -> f32 {
let scalefac = 2.0f32.powi(-i32::from(shift));
f32::from(coef) * scalefac
}
impl QuantizedParameters {
pub fn new(
coefs: &[i16],
order: usize,
shift: i8,
precision: usize,
) -> Result<Self, VerifyError> {
let ret = Self::from_parts(coefs, order, shift, precision);
ret.verify()?;
Ok(ret)
}
#[inline]
pub(crate) fn from_parts(coefs: &[i16], order: usize, shift: i8, precision: usize) -> Self {
debug_assert!(coefs.len() == order);
let mut coefs_v = simd::i16x32::default();
coefs_v[0..order].copy_from_slice(coefs);
Self {
coefs: coefs_v,
order,
shift,
precision,
}
}
#[inline]
pub const fn order(&self) -> usize {
self.order
}
#[inline]
pub const fn precision(&self) -> usize {
self.precision
}
#[inline]
pub const fn shift(&self) -> i8 {
self.shift
}
pub fn coefficient(&self, idx: usize) -> Option<i16> {
(idx < self.order()).then(|| self.coefs[idx])
}
#[inline]
pub(crate) fn coefs(&self) -> Vec<i16> {
(0..self.order()).map(|j| self.coefs[j]).collect()
}
#[inline]
#[allow(dead_code)]
pub(crate) fn dequantized(&self) -> Vec<f32> {
self.coefs()
.iter()
.map(|x| dequantize_parameter(*x, self.shift))
.collect()
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Residual {
partition_order: u8,
block_size: usize,
warmup_length: usize,
rice_params: Vec<u8>,
quotients: Vec<u32>, remainders: Vec<u32>,
sum_quotients: usize,
sum_rice_params: usize,
}
impl Residual {
pub fn new(
partition_order: usize,
block_size: usize,
warmup_length: usize,
rice_params: &[u8],
quotients: &[u32],
remainders: &[u32],
) -> Result<Self, VerifyError> {
let ret = Self::from_parts(
partition_order as u8,
block_size,
warmup_length,
rice_params.to_owned(),
quotients.to_owned(),
remainders.to_owned(),
);
ret.verify()?;
Ok(ret)
}
#[inline]
pub(crate) fn from_parts(
partition_order: u8,
block_size: usize,
warmup_length: usize,
rice_params: Vec<u8>,
quotients: Vec<u32>,
remainders: Vec<u32>,
) -> Self {
debug_assert!(rice_params.len() == 1usize << partition_order as usize);
let max_quotients: usize = find_max::<64>("ients) as usize;
let sum_quotients: usize = if max_quotients * block_size < u32::MAX as usize {
wrapping_sum::<u32, 32>("ients) as usize
} else {
quotients.iter().map(|x| *x as usize).sum()
};
let sum_rice_params: usize = rice_params.iter().map(|x| *x as usize).sum();
Self {
partition_order,
block_size,
warmup_length,
rice_params,
quotients,
remainders,
sum_quotients,
sum_rice_params,
}
}
#[inline]
pub fn partition_order(&self) -> usize {
self.partition_order as usize
}
#[inline]
pub fn rice_parameter(&self, p: usize) -> usize {
self.rice_params[p] as usize
}
pub fn residual(&self, t: usize) -> i32 {
let nparts = 1usize << self.partition_order as usize;
let part_id = t * nparts / self.block_size;
let quotient = self.quotients[t];
let shift = u32::from(self.rice_params[part_id]);
let remainder = self.remainders[t];
let v = (quotient << shift) + remainder;
rice::decode_signbit(v)
}
#[inline]
pub(crate) fn block_size(&self) -> usize {
self.block_size
}
#[inline]
pub(crate) fn warmup_length(&self) -> usize {
self.warmup_length
}
#[inline]
pub(crate) fn sum_quotients(&self) -> usize {
self.sum_quotients
}
#[inline]
pub(crate) fn sum_rice_params(&self) -> usize {
self.sum_rice_params
}
#[inline]
pub(crate) fn rice_params(&self) -> &[u8] {
&self.rice_params
}
#[inline]
pub(crate) fn quotients(&self) -> &[u32] {
&self.quotients
}
#[inline]
pub(crate) fn remainders(&self) -> &[u32] {
&self.remainders
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn channel_assignment_is_small_enough() {
let size = std::mem::size_of::<ChannelAssignment>();
assert_eq!(size, 2);
}
}