Subframe

Enum Subframe 

Source
pub enum Subframe<I> {
    Constant {
        block_size: u16,
        sample: I,
        wasted_bps: u32,
    },
    Verbatim {
        samples: Vec<I>,
        wasted_bps: u32,
    },
    Fixed {
        order: u8,
        warm_up: Vec<I>,
        residuals: Residuals<I>,
        wasted_bps: u32,
    },
    Lpc {
        order: NonZero<u8>,
        warm_up: Vec<I>,
        precision: SignedBitCount<15>,
        shift: u32,
        coefficients: Vec<i32>,
        residuals: Residuals<I>,
        wasted_bps: u32,
    },
}
Expand description

A FLAC’s frame’s subframe, one per channel

A subframe consists of a subframe header followed by subframe data.

Variants§

§

Constant

A CONSTANT subframe, in which all samples are identical

BitsField
subframe’s bits-per-samplesample

This single sample is repeated for all the samples in the subframe.

This is typically for long stretches of silence, or for the difference channel when both channels are identical in a stereo stream (false stereo).

§Example

use flac_codec::stream::Subframe;
use bitstream_io::{BitReader, BitRead, BigEndian, SignedBitCount};

let data: &[u8] = &[
    0b0_000000_0,  // subframe header
    0x00, 0x00,    // subframe data
];

let mut r = BitReader::endian(data, BigEndian);

assert_eq!(
    r.parse_using::<Subframe<i32>>((20, SignedBitCount::new::<16>())).unwrap(),
    Subframe::Constant {
        // taken from context
        block_size: 20,
        // constant subframes always have exactly one sample
        // this sample's size is a signed 16-bit value
        // taken from the subframe signed bit count
        sample: 0x00_00,
        // wasted bits-per-sample is taken from the subframe header
        wasted_bps: 0,
    },
);

Fields

§block_size: u16

the subframe’s block size in samples

§sample: I

The subframe’s sample

§wasted_bps: u32

Any wasted bits-per-sample

§

Verbatim

A VERBATIM subframe, in which all samples are stored uncompressed

BitsField
subframe’s bpssamples₀
subframe’s bpssamples₁
subframe’s bpssamples₂

The number of samples equals the frame’s block size.

This is for random noise which does not compress well by any other method.

§Example

use flac_codec::stream::Subframe;
use bitstream_io::{BitReader, BitRead, BigEndian, SignedBitCount};

let data: &[u8] = &[
    0b0_000001_0,  // subframe header
    // subframe data
    0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04,
    0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09,
    0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e,
    0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13,
];

let mut r = BitReader::endian(data, BigEndian);

assert_eq!(
    r.parse_using::<Subframe<i32>>((20, SignedBitCount::new::<16>())).unwrap(),
    Subframe::Verbatim {
        // the total number of samples equals the block size
        // (20 in this case)
        // each sample is a signed 16-bit value,
        // taken from the subframe signed bit count
        samples: vec![
            0x00, 0x01, 0x02, 0x03, 0x04,
            0x05, 0x06, 0x07, 0x08, 0x09,
            0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
            0x0f, 0x10, 0x11, 0x12, 0x13,
        ],
        // wasted bits-per-sample is taken from the subframe header
        wasted_bps: 0,
    },
);

Fields

§samples: Vec<I>

The subframe’s samples

§wasted_bps: u32

Any wasted bits-per-sample

§

Fixed

A FIXED subframe, encoded with a fixed set of parameters

BitsField
subframe’s bpswarm_up₀
subframe’s bpswarm_up₁
subframe’s bpswarm_up₂
Residuals

The number of warm-up simples equals the subframe’s predictor order (from the subframe header).

FIXED subframes have predictor coefficients that are defined by their predictor order. Because those coefficients require no floating-point math to calculate, these subframes can be encoded by limited hardware with no floating-point capabilities.

§Example

use flac_codec::stream::{Subframe, Residuals, ResidualPartition};
use bitstream_io::{BitReader, BitRead, BigEndian, BitCount, SignedBitCount};

let data: &[u8] = &[
    0b0_001100_0,  // subframe header
    // warm-up samples
    0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03,
    // residuals
    0x00, 0x3f, 0xff, 0xc0,
];

let mut r = BitReader::endian(data, BigEndian);

assert_eq!(
    r.parse_using::<Subframe<i32>>((20, SignedBitCount::new::<16>())).unwrap(),
    Subframe::Fixed {
        // predictor order is determined from subframe header
        order: 4,
        // the total number of warm-up samples equals the predictor order (4)
        // each warm-up sample is a signed 16-bit value,
        // taken from the subframe signed bit count
        warm_up: vec![0x00, 0x01, 0x02, 0x03],
        // the total number of residuals equals the block size
        // minus the predictor order,
        // which is 20 - 4 = 16 in this case
        residuals: Residuals::Method0 {
            partitions: vec![
                ResidualPartition::Standard {
                    rice: BitCount::new::<0>(),
                    residuals: vec![0; 16],
                }
            ],
        },
        // wasted bits-per-sample is taken from the subframe header
        wasted_bps: 0,
    },
);

Fields

§order: u8

The subframe’s predictor order from 0 to 4 (inclusive)

§warm_up: Vec<I>

The subframe’s warm-up samples (one per order)

§residuals: Residuals<I>

The subframe’s residuals

§wasted_bps: u32

Any wasted bits-per-sample

§

Lpc

An LPC subframe, encoded with a variable set of parameters

BitsField
subframe’s bpswarm_up₀
subframe’s bpswarm_up₁
subframe’s bpswarm_up₂
4precision (+1)
5shift
precisioncoefficients₀
precisioncoefficients₁
precisioncoefficients₂
Residuals

The number of warm-up samples and number of predictor coefficients is equal to the subframe’s predictor order (from the subframe header). The precision value is used to determine the size of the predictor coefficients. The shift value is stored as a signed integer, but negative shifts are not supported by the format and should be considered an error.

§Example

use flac_codec::stream::{Subframe, Residuals, ResidualPartition};
use bitstream_io::{BitReader, BitRead, BigEndian, BitCount, SignedBitCount};
use std::num::NonZero;

let data: &[u8] = &[
    0b0_100000_0,  // subframe header
    // warm-up sample
    0x00, 0x00,
    // precision + shift + coefficient
    0b1011_0101, 0b1_0111110, 0b00101_000,
    // residuals
    0x02, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x80,
];

let mut r = BitReader::endian(data, BigEndian);

assert_eq!(
    r.parse_using::<Subframe<i32>>((20, SignedBitCount::new::<16>())).unwrap(),
    Subframe::Lpc {
        // predictor order is determined from the subframe header
        order: NonZero::new(1).unwrap(),
        // the total number of warm-up samples equals the predictor order (1)
        // each warm-up sample is a signed 16-bit value,
        // taken from the subframe signed bit count
        warm_up: vec![0x00],
        // precision is a 4 bit value, plus one
        precision: SignedBitCount::new::<{0b1011 + 1}>(),  // 12 bits
        // shift is a 5 bit value
        shift: 0b0101_1,  // 11
        // the total number of coefficients equals the predictor order (1)
        // size of each coefficient is a signed 12-bit value (from precision)
        coefficients: vec![0b0111110_00101],  // 1989
        // the total number of residuals equals the block size
        // minus the predictor order,
        // which is 20 - 1 = 19 in this case
        residuals: Residuals::Method0 {
            partitions: vec![
                ResidualPartition::Standard {
                    rice: BitCount::new::<1>(),
                    residuals: vec![
                         1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
                         2, 2, 2, 2, 2, 2, 2, 2, 2
                    ],
                }
            ],
        },
        // wasted bits-per-sample is taken from the subframe header
        wasted_bps: 0,
    },
);

Fields

§order: NonZero<u8>

The subframe’s predictor order

§warm_up: Vec<I>

The subframe’s warm-up samples (one per order)

§precision: SignedBitCount<15>

The subframe’s QLP precision

§shift: u32

The subframe’s QLP shift

§coefficients: Vec<i32>

The subframe’s QLP coefficients (one per order)

§residuals: Residuals<I>

The subframe’s residuals

§wasted_bps: u32

Any wasted bits-per-sample

Implementations§

Source§

impl<I> Subframe<I>

Source

pub fn subframe_type(&self) -> SubframeType

Our subframe type

Source§

impl<I: SignedInteger> Subframe<I>

Source

pub fn decode(&self) -> Box<dyn Iterator<Item = I> + '_>

Decodes subframe to samples

Note that decoding subframes to samples using this method is intended for analysis purposes. The crate::decode module’s decoders are preferred for general-purpose decoding as they perform fewer temporary allocations.

Trait Implementations§

Source§

impl<I: Debug> Debug for Subframe<I>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl FromBitStreamUsing for Subframe<i32>

Source§

type Context = (u16, SignedBitCount<32>)

Some context to consume when parsing
Source§

type Error = Error

Error generated during parsing, such as io::Error
Source§

fn from_reader<R: BitRead + ?Sized>( r: &mut R, (block_size, bits_per_sample): (u16, SignedBitCount<32>), ) -> Result<Self, Error>

Parse Self from reader with the given context
Source§

impl FromBitStreamUsing for Subframe<i64>

Source§

type Context = (u16, SignedBitCount<33>)

Some context to consume when parsing
Source§

type Error = Error

Error generated during parsing, such as io::Error
Source§

fn from_reader<R: BitRead + ?Sized>( r: &mut R, (block_size, bits_per_sample): (u16, SignedBitCount<33>), ) -> Result<Self, Error>

Parse Self from reader with the given context
Source§

impl<I: PartialEq> PartialEq for Subframe<I>

Source§

fn eq(&self, other: &Subframe<I>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl ToBitStreamUsing for Subframe<i32>

Source§

type Context = SignedBitCount<32>

Some context to consume when writing
Source§

type Error = Error

Error generated during building, such as io::Error
Source§

fn to_writer<W: BitWrite + ?Sized>( &self, w: &mut W, bits_per_sample: SignedBitCount<32>, ) -> Result<(), Error>

Generate self to writer
Source§

fn bits<C>(&self, context: Self::Context) -> Result<C, Self::Error>
where C: Counter, Self: Sized,

Returns length of self in bits, if possible
Source§

impl ToBitStreamUsing for Subframe<i64>

Source§

type Context = SignedBitCount<33>

Some context to consume when writing
Source§

type Error = Error

Error generated during building, such as io::Error
Source§

fn to_writer<W: BitWrite + ?Sized>( &self, w: &mut W, bits_per_sample: SignedBitCount<33>, ) -> Result<(), Error>

Generate self to writer
Source§

fn bits<C>(&self, context: Self::Context) -> Result<C, Self::Error>
where C: Counter, Self: Sized,

Returns length of self in bits, if possible
Source§

impl<I: Eq> Eq for Subframe<I>

Source§

impl<I> StructuralPartialEq for Subframe<I>

Auto Trait Implementations§

§

impl<I> Freeze for Subframe<I>
where I: Freeze,

§

impl<I> RefUnwindSafe for Subframe<I>
where I: RefUnwindSafe,

§

impl<I> Send for Subframe<I>
where I: Send,

§

impl<I> Sync for Subframe<I>
where I: Sync,

§

impl<I> Unpin for Subframe<I>
where I: Unpin,

§

impl<I> UnwindSafe for Subframe<I>
where I: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.