libflo_audio/streaming/
encoder.rs1use crate::core::{ChannelData, FloResult, FrameType};
2use crate::lossless::Encoder;
3use crate::{compute_crc32, Reader, MAGIC};
4
5pub struct StreamingEncoder {
6 sample_rate: u32,
7 channels: u8,
8 bit_depth: u8,
9 compression_level: u8,
10 sample_buffer: Vec<f32>,
11 samples_per_frame: usize,
12 pending_frames: Vec<EncodedFrame>,
13 encoder: Encoder,
14 total_samples: u64,
15 frame_index: u32,
16}
17
18#[derive(Debug, Clone)]
20pub struct EncodedFrame {
21 pub index: u32,
23 pub timestamp_ms: u32,
25 pub data: Vec<u8>,
27 pub samples: u32,
29}
30
31impl StreamingEncoder {
32 pub fn new(sample_rate: u32, channels: u8, bit_depth: u8) -> Self {
34 let samples_per_frame = sample_rate as usize;
35
36 Self {
37 sample_rate,
38 channels,
39 bit_depth,
40 compression_level: 5,
41 sample_buffer: Vec::with_capacity(samples_per_frame * channels as usize * 2),
42 samples_per_frame,
43 pending_frames: Vec::new(),
44 encoder: Encoder::new(sample_rate, channels, bit_depth),
45 total_samples: 0,
46 frame_index: 0,
47 }
48 }
49
50 pub fn with_compression(mut self, level: u8) -> Self {
52 self.compression_level = level.min(9);
53 self.encoder =
54 Encoder::new(self.sample_rate, self.channels, self.bit_depth).with_compression(level);
55 self
56 }
57
58 pub fn pending_samples(&self) -> usize {
60 self.sample_buffer.len() / self.channels as usize
61 }
62
63 pub fn pending_frames(&self) -> usize {
65 self.pending_frames.len()
66 }
67
68 pub fn push_samples(&mut self, samples: &[f32]) -> FloResult<()> {
72 self.sample_buffer.extend_from_slice(samples);
73 self.try_encode_frames()?;
74 Ok(())
75 }
76
77 pub fn next_frame(&mut self) -> Option<EncodedFrame> {
79 if self.pending_frames.is_empty() {
80 None
81 } else {
82 Some(self.pending_frames.remove(0))
83 }
84 }
85
86 pub fn flush(&mut self) -> FloResult<Option<EncodedFrame>> {
88 if self.sample_buffer.is_empty() {
89 return Ok(None);
90 }
91
92 let samples_per_channel = self.sample_buffer.len() / self.channels as usize;
93 let timestamp_ms = (self.total_samples as f64 / self.sample_rate as f64 * 1000.0) as u32;
94
95 let frame_data = self.encode_frame_data(&self.sample_buffer)?;
96
97 let encoded = EncodedFrame {
98 index: self.frame_index,
99 timestamp_ms,
100 data: frame_data,
101 samples: samples_per_channel as u32,
102 };
103
104 self.total_samples += samples_per_channel as u64;
105 self.frame_index += 1;
106 self.sample_buffer.clear();
107
108 Ok(Some(encoded))
109 }
110
111 pub fn finalize(&mut self, metadata: &[u8]) -> FloResult<Vec<u8>> {
113 if let Some(frame) = self.flush()? {
114 self.pending_frames.push(frame);
115 }
116
117 let mut toc_data = Vec::new();
119 let num_frames = self.pending_frames.len() as u32;
120 toc_data.extend_from_slice(&num_frames.to_le_bytes());
121
122 let mut byte_offset: u64 = 0;
123 for frame in &self.pending_frames {
124 toc_data.extend_from_slice(&frame.index.to_le_bytes());
125 toc_data.extend_from_slice(&byte_offset.to_le_bytes());
126 toc_data.extend_from_slice(&(frame.data.len() as u32).to_le_bytes());
127 toc_data.extend_from_slice(&frame.timestamp_ms.to_le_bytes());
128 byte_offset += frame.data.len() as u64;
129 }
130
131 let mut data_chunk = Vec::new();
133 for frame in &self.pending_frames {
134 data_chunk.extend_from_slice(&frame.data);
135 }
136
137 let data_crc32 = compute_crc32(&data_chunk);
138
139 let header_size: u64 = 66;
140 let toc_size = toc_data.len() as u64;
141 let data_size = data_chunk.len() as u64;
142 let extra_size: u64 = 0;
143 let meta_size = metadata.len() as u64;
144
145 let mut output = Vec::new();
146
147 output.extend_from_slice(&MAGIC);
149
150 output.push(1); output.push(1); output.extend_from_slice(&0u16.to_le_bytes()); output.extend_from_slice(&self.sample_rate.to_le_bytes());
155 output.push(self.channels);
156 output.push(self.bit_depth);
157 output.extend_from_slice(&(self.pending_frames.len() as u64).to_le_bytes());
158 output.push(self.compression_level);
159 output.extend_from_slice(&[0u8; 3]); output.extend_from_slice(&data_crc32.to_le_bytes());
161 output.extend_from_slice(&header_size.to_le_bytes());
162 output.extend_from_slice(&toc_size.to_le_bytes());
163 output.extend_from_slice(&data_size.to_le_bytes());
164 output.extend_from_slice(&extra_size.to_le_bytes());
165 output.extend_from_slice(&meta_size.to_le_bytes());
166
167 output.extend_from_slice(&toc_data);
169
170 output.extend_from_slice(&data_chunk);
172
173 output.extend_from_slice(metadata);
175
176 self.pending_frames.clear();
177
178 Ok(output)
179 }
180
181 fn try_encode_frames(&mut self) -> FloResult<()> {
186 let frame_samples = self.samples_per_frame * self.channels as usize;
187
188 while self.sample_buffer.len() >= frame_samples {
189 let frame_data: Vec<f32> = self.sample_buffer.drain(..frame_samples).collect();
190 let timestamp_ms =
191 (self.total_samples as f64 / self.sample_rate as f64 * 1000.0) as u32;
192
193 let encoded_data = self.encode_frame_data(&frame_data)?;
194
195 self.pending_frames.push(EncodedFrame {
196 index: self.frame_index,
197 timestamp_ms,
198 data: encoded_data,
199 samples: self.samples_per_frame as u32,
200 });
201
202 self.total_samples += self.samples_per_frame as u64;
203 self.frame_index += 1;
204 }
205
206 Ok(())
207 }
208
209 fn encode_frame_data(&self, samples: &[f32]) -> FloResult<Vec<u8>> {
210 let temp_flo = self.encoder.encode(samples, &[])?;
211
212 let reader = Reader::new();
213 let file = reader.read(&temp_flo)?;
214
215 if file.frames.is_empty() {
216 return Err("No frames encoded".to_string());
217 }
218
219 let frame = &file.frames[0];
220 let mut data = Vec::new();
221
222 data.push(frame.frame_type);
224 data.extend_from_slice(&frame.frame_samples.to_le_bytes());
225 data.push(frame.flags);
226
227 for ch in &frame.channels {
229 let ch_data = self.serialize_channel(ch, FrameType::from(frame.frame_type));
230 data.extend_from_slice(&(ch_data.len() as u32).to_le_bytes());
231 data.extend_from_slice(&ch_data);
232 }
233
234 Ok(data)
235 }
236
237 fn serialize_channel(&self, ch: &ChannelData, frame_type: FrameType) -> Vec<u8> {
238 match frame_type {
239 FrameType::Silence => vec![],
240 FrameType::Raw | FrameType::Transform => ch.residuals.clone(),
241 _ => {
242 let mut data = Vec::new();
243 data.push(ch.rice_parameter);
244 for &coeff in &ch.predictor_coeffs {
245 data.extend_from_slice(&coeff.to_le_bytes());
246 }
247 data.extend_from_slice(&ch.residuals);
248 data
249 }
250 }
251 }
252}