pub mod crc;
pub mod data;
pub mod error;
pub mod frame;
pub mod lpc;
pub mod metadata;
pub mod rice;
pub mod subframe;
mod bitstream;
mod constants;
mod flac_file;
pub use error::FlacError;
pub use flac_file::{FlacFile, FlacFileInfo, write_flac};
pub use metadata::{
MetadataBlock, MetadataBlockType, SeekPoint, SeekTable, StreamInfo, VorbisComment,
};
use core::fmt::{Display, Formatter, Result as FmtResult};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct CompressionLevel(u8);
impl CompressionLevel {
pub const FASTEST: Self = Self(0);
pub const FAST: Self = Self(2);
pub const DEFAULT: Self = Self(5);
pub const BEST: Self = Self(8);
pub const fn new(level: u8) -> Self {
Self(if level > 8 { 8 } else { level })
}
pub const fn level(self) -> u8 {
self.0
}
pub const fn block_size(self) -> u32 {
match self.0 {
0 => 1152,
1 => 1152,
2 => 2304,
3 => 2304,
4 => 4096,
5 => 4096,
6 => 4096,
7 => 4096,
8 => 4096,
_ => 4096,
}
}
pub const fn max_lpc_order(self) -> u8 {
match self.0 {
0 => 0, 1 => 0, 2 => 0, 3 => 6,
4 => 8,
5 => 8,
6 => 8,
7 => 12,
8 => 12,
_ => 8,
}
}
pub const fn exhaustive_rice_search(self) -> bool {
self.0 >= 6
}
pub const fn exhaustive_lpc_search(self) -> bool {
self.0 >= 7
}
pub const fn rice_partition_order_range(self) -> (u8, u8) {
match self.0 {
0 => (0, 3),
1 => (0, 3),
2 => (0, 4),
3 => (0, 4),
4 => (0, 5),
5 => (0, 5),
6 => (0, 6),
7 => (0, 6),
8 => (0, 6),
_ => (0, 5),
}
}
pub const fn try_mid_side(self) -> bool {
self.0 >= 1
}
pub const fn qlp_precision(self) -> u8 {
match self.0 {
0..=4 => 12,
5..=7 => 14,
8 => 15,
_ => 12,
}
}
}
impl Display for CompressionLevel {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(
f,
"Level {} ({})",
self.0,
match self.0 {
0 => "fastest",
1..=2 => "fast",
3..=4 => "normal",
5 => "default",
6..=7 => "high",
8 => "best",
_ => "unknown",
}
)
}
}
impl From<u8> for CompressionLevel {
fn from(level: u8) -> Self {
Self::new(level)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ChannelAssignment {
Independent(u8),
LeftSide,
RightSide,
MidSide,
}
impl ChannelAssignment {
pub const fn code(self) -> u8 {
match self {
ChannelAssignment::Independent(n) => n - 1,
ChannelAssignment::LeftSide => 0b1000,
ChannelAssignment::RightSide => 0b1001,
ChannelAssignment::MidSide => 0b1010,
}
}
pub const fn from_code(code: u8) -> Option<Self> {
match code {
0..=7 => Some(ChannelAssignment::Independent(code + 1)),
0b1000 => Some(ChannelAssignment::LeftSide),
0b1001 => Some(ChannelAssignment::RightSide),
0b1010 => Some(ChannelAssignment::MidSide),
_ => None,
}
}
pub const fn channels(self) -> u8 {
match self {
ChannelAssignment::Independent(n) => n,
ChannelAssignment::LeftSide
| ChannelAssignment::RightSide
| ChannelAssignment::MidSide => 2,
}
}
pub const fn is_stereo_decorrelated(self) -> bool {
matches!(
self,
ChannelAssignment::LeftSide | ChannelAssignment::RightSide | ChannelAssignment::MidSide
)
}
}
impl Display for ChannelAssignment {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
ChannelAssignment::Independent(n) => write!(f, "{} independent channel(s)", n),
ChannelAssignment::LeftSide => write!(f, "left-side stereo"),
ChannelAssignment::RightSide => write!(f, "right-side stereo"),
ChannelAssignment::MidSide => write!(f, "mid-side stereo"),
}
}
}