anni_flac/blocks/
stream_info.rs

1use crate::prelude::*;
2use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
3use std::fmt;
4use std::io::{Read, Write};
5
6/// Notes:
7/// FLAC specifies a minimum block size of 16 and a maximum block size of 65535,
8/// meaning the bit patterns corresponding to the numbers 0-15 in the minimum blocksize and maximum blocksize fields are invalid.
9pub struct BlockStreamInfo {
10    /// <16> The minimum block size (in samples) used in the stream.
11    pub min_block_size: u16,
12    /// <16> The maximum block size (in samples) used in the stream.
13    pub max_block_size: u16,
14    /// <24> The minimum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
15    pub min_frame_size: u32,
16    /// <24> The maximum frame size (in bytes) used in the stream. May be 0 to imply the value is not known.
17    pub max_frame_size: u32,
18    /// <20> Sample rate in Hz.
19    /// Though 20 bits are available, the maximum sample rate is limited by the structure of frame headers to 655350Hz.
20    /// Also, a value of 0 is invalid.
21    pub sample_rate: u32,
22    /// <3> (number of channels)-1.
23    /// FLAC supports from 1 to 8 channels
24    pub channels: u8,
25    /// <5> (bits per sample)-1.
26    /// FLAC supports from 4 to 32 bits per sample.
27    /// Currently the reference encoder and decoders only support up to 24 bits per sample.
28    pub bits_per_sample: u8,
29    /// <36> Total samples in stream.
30    /// 'Samples' means inter-channel sample, i.e. one second of 44.1Khz audio will have 44100 samples regardless of the number of channels.
31    /// A value of zero here means the number of total samples is unknown.
32    pub total_samples: u64,
33    /// <128> MD5 signature of the unencoded audio data.
34    /// This allows the decoder to determine if an error exists in the audio data even when the error does not result in an invalid bitstream.
35    pub md5_signature: [u8; 16],
36}
37
38impl BlockStreamInfo {
39    /// (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream.
40    pub fn is_fixed_blocksize_stream(&self) -> bool {
41        self.min_block_size == self.max_block_size
42    }
43}
44
45impl Decode for BlockStreamInfo {
46    fn from_reader<R: Read>(reader: &mut R) -> Result<Self> {
47        let min_block_size = reader.read_u16::<BigEndian>()?;
48        let max_block_size = reader.read_u16::<BigEndian>()?;
49        let min_frame_size = reader.read_u24::<BigEndian>()?;
50        let max_frame_size = reader.read_u24::<BigEndian>()?;
51
52        let mut sample_region = [0u8; 8];
53        reader.read_exact(&mut sample_region)?;
54        // 20 bits
55        let sample_rate = ((sample_region[0] as u32) << 12)
56            + ((sample_region[1] as u32) << 4)
57            + ((sample_region[2] as u32) >> 4);
58        // 3 bits
59        let channels = ((sample_region[2] >> 1) & 0b00000111) + 1;
60        // 5 bits
61        let bits_per_sample = ((sample_region[2] & 0b00000001) << 4) + (sample_region[3] >> 4) + 1;
62        // 36 bits
63        let total_samples = ((sample_region[3] as u64 & 0b00001111) << 32)
64            + ((sample_region[4] as u64) << 24)
65            + ((sample_region[5] as u64) << 16)
66            + ((sample_region[6] as u64) << 8)
67            + (sample_region[7] as u64);
68        let mut md5_signature = [0u8; 16];
69        reader.read_exact(&mut md5_signature)?;
70
71        Ok(BlockStreamInfo {
72            min_block_size,
73            max_block_size,
74            min_frame_size,
75            max_frame_size,
76            sample_rate,
77            channels,
78            bits_per_sample,
79            total_samples,
80            md5_signature,
81        })
82    }
83}
84
85#[cfg(feature = "async")]
86#[async_trait::async_trait]
87impl AsyncDecode for BlockStreamInfo {
88    async fn from_async_reader<R>(reader: &mut R) -> Result<Self>
89    where
90        R: AsyncRead + Unpin + Send,
91    {
92        use crate::utils::*;
93
94        let min_block_size = reader.read_u16().await?;
95        let max_block_size = reader.read_u16().await?;
96        let min_frame_size = read_u24_async(reader).await?;
97        let max_frame_size = read_u24_async(reader).await?;
98
99        let mut sample_region = [0u8; 8];
100        reader.read_exact(&mut sample_region).await?;
101        // 20 bits
102        let sample_rate = ((sample_region[0] as u32) << 12)
103            + ((sample_region[1] as u32) << 4)
104            + ((sample_region[2] as u32) >> 4);
105        // 3 bits
106        let channels = ((sample_region[2] >> 1) & 0b00000111) + 1;
107        // 5 bits
108        let bits_per_sample = ((sample_region[2] & 0b00000001) << 4) + (sample_region[3] >> 4) + 1;
109        // 36 bits
110        let total_samples = ((sample_region[3] as u64 & 0b00001111) << 32)
111            + ((sample_region[4] as u64) << 24)
112            + ((sample_region[5] as u64) << 16)
113            + ((sample_region[6] as u64) << 8)
114            + (sample_region[7] as u64);
115        let mut md5_signature = [0u8; 16];
116        reader.read_exact(&mut md5_signature).await?;
117
118        Ok(BlockStreamInfo {
119            min_block_size,
120            max_block_size,
121            min_frame_size,
122            max_frame_size,
123            sample_rate,
124            channels,
125            bits_per_sample,
126            total_samples,
127            md5_signature,
128        })
129    }
130}
131
132impl Encode for BlockStreamInfo {
133    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
134        writer.write_u16::<BigEndian>(self.min_block_size)?;
135        writer.write_u16::<BigEndian>(self.max_block_size)?;
136        writer.write_u24::<BigEndian>(self.min_frame_size)?;
137        writer.write_u24::<BigEndian>(self.max_frame_size)?;
138
139        // 16/20 bits
140        writer.write_u16::<BigEndian>((self.sample_rate >> 4) as u16)?;
141        let channels = self.channels - 1;
142        let bps = self.bits_per_sample - 1;
143        writer.write_u48::<BigEndian>(
144            // 4 bits of sample rate + 3 bits of channel num + 1 bit bps
145            ((((((self.sample_rate & 0b1111) as u8) << 4) + ((channels & 0b111) << 1) + (bps >> 4))
146                as u64)
147                << 40)
148                + (((bps & 0b1111) as u64) << 36)
149                + self.total_samples,
150        )?;
151        writer.write_all(&self.md5_signature)?;
152        Ok(())
153    }
154}
155
156impl fmt::Debug for BlockStreamInfo {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        let mut prefix = "".to_owned();
159        if let Some(width) = f.width() {
160            prefix = " ".repeat(width);
161        }
162        writeln!(
163            f,
164            "{prefix}minimum blocksize: {} samples",
165            self.min_block_size,
166            prefix = prefix
167        )?;
168        writeln!(
169            f,
170            "{prefix}maximum blocksize: {} samples",
171            self.max_block_size,
172            prefix = prefix
173        )?;
174        writeln!(
175            f,
176            "{prefix}minimum framesize: {} bytes",
177            self.min_frame_size,
178            prefix = prefix
179        )?;
180        writeln!(
181            f,
182            "{prefix}maximum framesize: {} bytes",
183            self.max_frame_size,
184            prefix = prefix
185        )?;
186        writeln!(
187            f,
188            "{prefix}sample_rate: {} Hz",
189            self.sample_rate,
190            prefix = prefix
191        )?;
192        writeln!(f, "{prefix}channels: {}", self.channels, prefix = prefix)?;
193        writeln!(
194            f,
195            "{prefix}bits-per-sample: {}",
196            self.bits_per_sample,
197            prefix = prefix
198        )?;
199        writeln!(
200            f,
201            "{prefix}total samples: {}",
202            self.total_samples,
203            prefix = prefix
204        )?;
205        writeln!(
206            f,
207            "{prefix}MD5 signature: {}",
208            hex::encode(self.md5_signature),
209            prefix = prefix
210        )?;
211        Ok(())
212    }
213}