///|
/// The `STREAMINFO` metadata block: the fixed 34-byte header every FLAC
/// stream starts with, describing sample rate, channel layout, bit depth and
/// the total sample count.
/// Decoded `STREAMINFO` fields. All sizes are in bytes, the sample rate in Hz,
/// `channels` is 1..=8 and `bits_per_sample` the per-channel PCM bit depth.
pub struct StreamInfo {
min_block_size : Int
max_block_size : Int
min_frame_size : Int
max_frame_size : Int
sample_rate : Int
channels : Int
bits_per_sample : Int
total_samples : Int64
md5 : Array[Byte]
}
/// Build a `StreamInfo` value from already-decoded fields.
pub fn StreamInfo::new(
min_block_size : Int,
max_block_size : Int,
min_frame_size : Int,
max_frame_size : Int,
sample_rate : Int,
channels : Int,
bits_per_sample : Int,
total_samples : Int64,
md5 : Array[Byte]
) -> StreamInfo {
{
min_block_size: min_block_size,
max_block_size: max_block_size,
min_frame_size: min_frame_size,
max_frame_size: max_frame_size,
sample_rate: sample_rate,
channels: channels,
bits_per_sample: bits_per_sample,
total_samples: total_samples,
md5: md5,
}
}
/// Parse a 34-byte `STREAMINFO` block from a byte-aligned reader, returning the
/// decoded info and the reader advanced past the block.
pub fn BitReader::read_streaminfo(self : BitReader) -> (StreamInfo, BitReader) raise DecodeError {
let (min_block, r1) = self.read_u16()
let (max_block, r2) = r1.read_u16()
let (min_frame, r3) = r2.read_u24()
let (max_frame, r4) = r3.read_u24()
let (sample_rate, r5) = r4.read_bits(20)
let (ch, r6) = r5.read_bits(3)
let (bps, r7) = r6.read_bits(5)
let (hi, r8) = r7.read_bits(4)
let (lo, r9) = r8.read_bits(32)
let total = (Int64::from_int(hi) << 32) | (Int64::from_int(lo) & 4294967295L)
let mut r = r9
let md5 = Array::make(16, b'\x00')
for i in 0..<16 {
let (b, rr) = r.read_byte()
md5.set(i, b.to_byte())
r = rr
}
(StreamInfo::new(min_block, max_block, min_frame, max_frame, sample_rate, ch + 1, bps + 1, total, md5), r)
}
/// Parse a standalone 34-byte `STREAMINFO` block.
pub fn parse_streaminfo(data : Bytes) -> StreamInfo raise DecodeError {
if data.length() != 34 {
raise InvalidMetadata
}
let (info, _) = BitReader::new(data).read_streaminfo()
info
}