anni_flac/blocks/
stream_info.rs1use crate::prelude::*;
2use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
3use std::fmt;
4use std::io::{Read, Write};
5
6pub struct BlockStreamInfo {
10 pub min_block_size: u16,
12 pub max_block_size: u16,
14 pub min_frame_size: u32,
16 pub max_frame_size: u32,
18 pub sample_rate: u32,
22 pub channels: u8,
25 pub bits_per_sample: u8,
29 pub total_samples: u64,
33 pub md5_signature: [u8; 16],
36}
37
38impl BlockStreamInfo {
39 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 let sample_rate = ((sample_region[0] as u32) << 12)
56 + ((sample_region[1] as u32) << 4)
57 + ((sample_region[2] as u32) >> 4);
58 let channels = ((sample_region[2] >> 1) & 0b00000111) + 1;
60 let bits_per_sample = ((sample_region[2] & 0b00000001) << 4) + (sample_region[3] >> 4) + 1;
62 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 let sample_rate = ((sample_region[0] as u32) << 12)
103 + ((sample_region[1] as u32) << 4)
104 + ((sample_region[2] as u32) >> 4);
105 let channels = ((sample_region[2] >> 1) & 0b00000111) + 1;
107 let bits_per_sample = ((sample_region[2] & 0b00000001) << 4) + (sample_region[3] >> 4) + 1;
109 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 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 ((((((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}