1#[cfg(feature = "alloc")]
13extern crate alloc;
14
15use super::{
16 attack_detector::AttackDetector, bandwidth_detector::BandwidthDetector, bitstream_encoding::BitstreamEncoding,
17 long_term_post_filter::LongTermPostFilter, modified_dct::ModDiscreteCosTrans,
18 noise_level_estimation::NoiseLevelEstimation, residual_spectrum::ResidualBitsEncoder,
19 spectral_noise_shaping::SpectralNoiseShaping, spectral_quantization::SpectralQuantization,
20 temporal_noise_shaping::TemporalNoiseShaping,
21};
22use crate::common::{
23 complex::{Complex, Scaler},
24 config::{FrameDuration, Lc3Config, SamplingFrequency},
25};
26
27#[derive(Debug)]
30pub enum Lc3EncoderError {}
31
32#[cfg(feature = "alloc")]
33pub struct Lc3Encoder<'a> {
34 channels: alloc::vec::Vec<EncoderChannel<'a>>,
35}
36
37#[cfg(not(feature = "alloc"))]
38pub struct Lc3Encoder<'a, const NUM_CHANNELS: usize = 2> {
39 channels: heapless::Vec<EncoderChannel<'a>, NUM_CHANNELS>,
40}
41
42struct EncoderChannel<'a> {
43 config: Lc3Config,
44 mdct: ModDiscreteCosTrans<'a>,
45 bandwidth_detector: BandwidthDetector,
46 attack_detector: AttackDetector,
47 spectral_noise_shaping: SpectralNoiseShaping,
48 temporal_noise_shaping: TemporalNoiseShaping,
49 long_term_post_filter: LongTermPostFilter<'a>,
50 spectral_quantization: SpectralQuantization,
51 noise_level_estimation: NoiseLevelEstimation,
52 bitstream_encoding: BitstreamEncoding,
53 frame_index: usize,
54
55 energy_bands: &'a mut [Scaler],
57 mdct_out: &'a mut [Scaler],
58 spec_quant_out: &'a mut [i16],
59 residual: ResidualBitsEncoder,
60}
61
62impl<'a> EncoderChannel<'a> {
63 pub fn encode(&mut self, x_s: &[i16], buf_out: &mut [u8]) -> Result<(), Lc3EncoderError> {
64 self.frame_index += 1;
65 let nbits = buf_out.len() * 8;
66
67 let near_nyquist_flag = self.mdct.run(x_s, self.mdct_out, self.energy_bands);
69
70 let (spec_lines, _) = self.mdct_out.split_at_mut(self.config.ne);
72
73 let bandwidth = self.bandwidth_detector.run(self.energy_bands);
75
76 let attack_detected = self.attack_detector.run(x_s, buf_out.len());
78
79 let sns = self
81 .spectral_noise_shaping
82 .run(spec_lines, self.energy_bands, attack_detected);
83
84 let tns = self
86 .temporal_noise_shaping
87 .run(spec_lines, bandwidth.bandwidth_ind, nbits, near_nyquist_flag);
88
89 let post_filter = self.long_term_post_filter.run(x_s, near_nyquist_flag, nbits);
91
92 let spec = self.spectral_quantization.run(
94 spec_lines, self.spec_quant_out, nbits, bandwidth.nbits_bandwidth, tns.nbits_tns, post_filter.nbits_ltpf,
95 );
96
97 let residual_bits = self.residual.encode(
99 spec.nbits_spec, spec.nbits_trunc, self.config.ne, spec.gg, spec_lines, self.spec_quant_out,
100 );
101
102 let noise_factor = self.noise_level_estimation.calc_noise_factor(
104 spec_lines, self.spec_quant_out, bandwidth.bandwidth_ind, spec.gg as Scaler,
105 );
106
107 self.bitstream_encoding.encode(
108 bandwidth, sns, tns, post_filter, spec, residual_bits, noise_factor, self.spec_quant_out, buf_out,
109 );
110
111 Ok(())
112 }
113}
114
115#[cfg(feature = "alloc")]
116impl<'a> Lc3Encoder<'a> {
117 pub fn new(
118 num_channels: usize,
119 frame_duration: FrameDuration,
120 sampling_frequency: SamplingFrequency,
121 integer_buf: &'a mut [i16],
122 scaler_buf: &'a mut [Scaler],
123 complex_buf: &'a mut [Complex],
124 ) -> Self {
125 let config = Lc3Config::new(sampling_frequency, frame_duration);
126 let mut channels: alloc::vec::Vec<EncoderChannel<'a>> = alloc::vec::Vec::new();
127
128 let mut integer_buf_save = integer_buf;
129 let mut scaler_buf_save = scaler_buf;
130 let mut complex_buf_save = complex_buf;
131
132 for _ in 0..num_channels {
133 let (mdct, integer_buf, complex_buf) = ModDiscreteCosTrans::new(config, integer_buf_save, complex_buf_save);
134 let bandwidth_detector = BandwidthDetector::new(config.n_ms, config.fs_ind);
135 let attack_detector = AttackDetector::new(config);
136 let spectral_noise_shaping = SpectralNoiseShaping::new(config, mdct.get_i_fs());
137 let temporal_noise_shaping = TemporalNoiseShaping::new(config);
138 let (long_term_post_filter, scaler_buf, integer_buf) =
139 LongTermPostFilter::new(config, scaler_buf_save, integer_buf);
140 let spectral_quantization = SpectralQuantization::new(config.ne, config.fs_ind);
141 let noise_level_estimation = NoiseLevelEstimation::new(config.n_ms, config.ne);
142 let bitstream_encoding = BitstreamEncoding::new(config.ne);
143 let (output, scaler_buf) = scaler_buf.split_at_mut(config.nf);
144 let (energy_bands, scaler_buf) = scaler_buf.split_at_mut(config.nb);
145 let residual = ResidualBitsEncoder::default();
146 let (x_q, integer_buf) = integer_buf.split_at_mut(config.ne);
147
148 let channel = EncoderChannel {
149 mdct,
150 bandwidth_detector,
151 attack_detector,
152 spectral_noise_shaping,
153 temporal_noise_shaping,
154 long_term_post_filter,
155 spectral_quantization,
156 noise_level_estimation,
157 bitstream_encoding,
158 frame_index: 0,
159 mdct_out: output,
160 energy_bands,
161 residual,
162 config,
163 spec_quant_out: x_q,
164 };
165
166 channels.push(channel);
167 integer_buf_save = integer_buf;
168 scaler_buf_save = scaler_buf;
169 complex_buf_save = complex_buf;
170 }
171
172 Self { channels }
173 }
174
175 pub fn encode_frame(
176 &mut self,
177 channel_index: usize,
178 samples_in: &[i16],
179 buf_out: &mut [u8],
180 ) -> Result<(), Lc3EncoderError> {
181 if channel_index < self.channels.len() {
182 let channel = &mut self.channels[channel_index];
183 channel.encode(samples_in, buf_out)
184 } else {
185 panic!(
186 "Cannot decode channel index {} as config only specifies {} channels",
187 channel_index,
188 self.channels.len()
189 );
190 }
191 }
192
193 pub const fn calc_working_buffer_lengths(
195 num_channels: usize,
196 frame_duration: FrameDuration,
197 sampling_frequency: SamplingFrequency,
198 ) -> (usize, usize, usize) {
199 let config = Lc3Config::new(sampling_frequency, frame_duration);
200 let (mdct_integer_len, mdct_complex_len) = ModDiscreteCosTrans::calc_working_buffer_lengths(&config);
201 let (ltpf_integer_len, ltpf_scaler_len) = LongTermPostFilter::calc_working_buffer_length(&config);
202 let scaler_len = ltpf_scaler_len + config.nf + config.nb;
203 let integer_len = mdct_integer_len + ltpf_integer_len + config.ne;
204 (
205 integer_len * num_channels,
206 scaler_len * num_channels,
207 mdct_complex_len * num_channels,
208 )
209 }
210}
211
212#[cfg(not(feature = "alloc"))]
213impl<'a, const NUM_CHANNELS: usize> Lc3Encoder<'a, NUM_CHANNELS> {
214 pub fn new(
215 frame_duration: FrameDuration,
216 sampling_frequency: SamplingFrequency,
217 integer_buf: &'a mut [i16],
218 scaler_buf: &'a mut [Scaler],
219 complex_buf: &'a mut [Complex],
220 ) -> Self {
221 let config = Lc3Config::new(sampling_frequency, frame_duration);
222 let mut channels: heapless::Vec<EncoderChannel<'a>, NUM_CHANNELS> = heapless::Vec::new();
223
224 let mut integer_buf_save = integer_buf;
225 let mut scaler_buf_save = scaler_buf;
226 let mut complex_buf_save = complex_buf;
227
228 for _ in 0..NUM_CHANNELS {
229 let (mdct, integer_buf, complex_buf) = ModDiscreteCosTrans::new(config, integer_buf_save, complex_buf_save);
230 let bandwidth_detector = BandwidthDetector::new(config.n_ms, config.fs_ind);
231 let attack_detector = AttackDetector::new(config);
232 let spectral_noise_shaping = SpectralNoiseShaping::new(config, mdct.get_i_fs());
233 let temporal_noise_shaping = TemporalNoiseShaping::new(config);
234 let (long_term_post_filter, scaler_buf, integer_buf) =
235 LongTermPostFilter::new(config, scaler_buf_save, integer_buf);
236 let spectral_quantization = SpectralQuantization::new(config.ne, config.fs_ind);
237 let noise_level_estimation = NoiseLevelEstimation::new(config.n_ms, config.ne);
238 let bitstream_encoding = BitstreamEncoding::new(config.ne);
239 let (output, scaler_buf) = scaler_buf.split_at_mut(config.nf);
240 let (energy_bands, scaler_buf) = scaler_buf.split_at_mut(config.nb);
241 let residual = ResidualBitsEncoder::default();
242 let (x_q, integer_buf) = integer_buf.split_at_mut(config.ne);
243
244 let channel = EncoderChannel {
245 mdct,
246 bandwidth_detector,
247 attack_detector,
248 spectral_noise_shaping,
249 temporal_noise_shaping,
250 long_term_post_filter,
251 spectral_quantization,
252 noise_level_estimation,
253 bitstream_encoding,
254 frame_index: 0,
255 mdct_out: output,
256 energy_bands,
257 residual,
258 config,
259 spec_quant_out: x_q,
260 };
261
262 channels.push(channel).ok();
263 integer_buf_save = integer_buf;
264 scaler_buf_save = scaler_buf;
265 complex_buf_save = complex_buf;
266 }
267
268 Self { channels }
269 }
270
271 pub fn encode_frame(
272 &mut self,
273 channel_index: usize,
274 samples_in: &[i16],
275 buf_out: &mut [u8],
276 ) -> Result<(), Lc3EncoderError> {
277 if channel_index < NUM_CHANNELS {
278 let channel = &mut self.channels[channel_index];
279 channel.encode(samples_in, buf_out)
280 } else {
281 panic!(
282 "Cannot decode channel index {} as config only specifies {} channels",
283 channel_index, NUM_CHANNELS
284 );
285 }
286 }
287
288 pub const fn calc_working_buffer_lengths(
290 frame_duration: FrameDuration,
291 sampling_frequency: SamplingFrequency,
292 ) -> (usize, usize, usize) {
293 let config = Lc3Config::new(sampling_frequency, frame_duration);
294 let (mdct_integer_len, mdct_complex_len) = ModDiscreteCosTrans::calc_working_buffer_lengths(&config);
295 let (ltpf_integer_len, ltpf_scaler_len) = LongTermPostFilter::calc_working_buffer_length(&config);
296 let scaler_len = ltpf_scaler_len + config.nf + config.nb;
297 let integer_len = mdct_integer_len + ltpf_integer_len + config.ne;
298 (
299 integer_len * NUM_CHANNELS,
300 scaler_len * NUM_CHANNELS,
301 mdct_complex_len * NUM_CHANNELS,
302 )
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 extern crate std;
309 use super::*;
310 use crate::common::config::{FrameDuration, SamplingFrequency};
311
312 #[cfg(feature = "alloc")]
313 #[test]
314 fn lc3_encode_channel() {
315 const NUM_CH: usize = 1;
316 const DURATION: FrameDuration = FrameDuration::TenMs;
317 const FREQ: SamplingFrequency = SamplingFrequency::Hz48000;
318 const BUF_LENGTHS: (usize, usize, usize) = Lc3Encoder::calc_working_buffer_lengths(NUM_CH, DURATION, FREQ);
319 let mut integer_buf = [0; BUF_LENGTHS.0];
320 let mut scaler_buf = [0.0; BUF_LENGTHS.1];
321 let mut complex_buf = [Complex::default(); BUF_LENGTHS.2];
322
323 let mut encoder = Lc3Encoder::new(
324 NUM_CH, DURATION, FREQ, &mut integer_buf, &mut scaler_buf, &mut complex_buf,
325 );
326 let samples_in = [
327 836, 739, 638, 510, 352, 200, 72, -56, -177, -297, -416, -520, -623, -709, -791, -911, -1062, -1199, -1298,
328 -1375, -1433, -1484, -1548, -1603, -1648, -1687, -1724, -1744, -1730, -1699, -1650, -1613, -1594, -1563,
329 -1532, -1501, -1473, -1441, -1409, -1393, -1355, -1280, -1201, -1118, -1032, -953, -860, -741, -613, -477,
330 -355, -261, -168, -80, -8, 57, 127, 217, 296, 347, 385, 413, 456, 517, 575, 640, 718, 806, 888, 963, 1041,
331 1080, 1081, 1083, 1072, 1062, 1067, 1056, 1035, 1019, 999, 964, 934, 909, 876, 854, 835, 813, 795, 781,
332 783, 772, 750, 747, 728, 713, 726, 716, 680, 638, 580, 516, 451, 393, 351, 307, 244, 161, 79, 18, -45,
333 -123, -215, -301, -389, -512, -644, -764, -888, -1006, -1126, -1253, -1378, -1500, -1614, -1716, -1813,
334 -1926, -2051, -2176, -2301, -2416, -2514, -2595, -2680, -2783, -2883, -2977, -3068, -3163, -3262, -3341,
335 -3381, -3392, -3392, -3379, -3368, -3353, -3318, -3292, -3244, -3169, -3109, -3049, -2989, -2922, -2844,
336 -2790, -2743, -2672, -2588, -2490, -2371, -2222, -2046, -1861, -1695, -1546, -1384, -1214, -1058, -913,
337 -761, -602, -441, -280, -124, 24, 169, 302, 421, 546, 661, 738, 796, 851, 924, 1055, 1227, 1412, 1588,
338 1707, 1787, 1853, 1905, 1963, 2015, 2048, 2072, 2082, 2093, 2099, 2095, 2097, 2086, 2063, 2060, 2069, 2052,
339 2012, 1977, 1956, 1948, 1918, 1843, 1748, 1641, 1533, 1435, 1342, 1252, 1163, 1081, 1024, 989, 962, 937,
340 911, 879, 841, 769, 657, 541, 445, 365, 289, 202, 104, -4, -119, -245, -381, -523, -655, -770, -874, -957,
341 -1017, -1069, -1118, -1173, -1256, -1370, -1497, -1629, -1745, -1827, -1882, -1934, -2021, -2115, -2165,
342 -2196, -2230, -2258, -2282, -2302, -2320, -2332, -2340, -2344, -2338, -2313, -2269, -2215, -2152, -2072,
343 -1978, -1885, -1793, -1704, -1621, -1528, -1419, -1310, -1213, -1116, -1014, -914, -820, -736, -656, -578,
344 -514, -445, -358, -276, -206, -136, -62, 0, 56, 124, 190, 253, 316, 379, 458, 552, 630, 686, 725, 735, 709,
345 661, 612, 572, 538, 507, 476, 453, 448, 453, 444, 415, 370, 316, 257, 203, 159, 125, 107, 114, 137, 162,
346 181, 189, 186, 166, 145, 145, 154, 154, 161, 184, 200, 217, 254, 294, 325, 332, 320, 302, 286, 273, 260,
347 266, 294, 297, 274, 251, 221, 170, 100, 29, -31, -82, -134, -187, -232, -278, -347, -426, -490, -548, -613,
348 -677, -727, -755, -769, -770, -757, -741, -729, -713, -684, -659, -647, -631, -606, -588, -585, -577, -555,
349 -534, -527, -528, -513, -480, -456, -440, -415, -382, -333, -244, -132, -32, 47, 130, 225, 308, 383, 460,
350 533, 607, 687, 757, 817, 889, 977, 1038, 1064, 1100, 1165, 1250, 1349, 1456, 1563, 1665, 1755, 1829, 1890,
351 1935, 1973, 2008, 2033, 2044, 2054, 2076, 2106, 2125, 2115, 2097, 2092, 2093, 2082, 2067, 2068, 2095, 2135,
352 2169, 2193, 2213, 2219, 2202, 2163, 2101, 2033, 1992, 1985, 1990, 1986, 1978, 1977, 1976, 1969, 1959, 1956,
353 1960, 1955, 1930, 1907, 1884, 1844, 1790, 1733, 1687, 1649, 1611, 1586,
354 ];
355 let mut buf_out = [0; 150];
356
357 encoder.encode_frame(0, &samples_in, &mut buf_out).unwrap();
358
359 let buf_out_expected = [
360 230, 243, 160, 169, 152, 75, 36, 156, 223, 96, 241, 214, 150, 248, 180, 106, 115, 92, 147, 213, 56, 100,
361 96, 52, 194, 178, 44, 31, 222, 246, 83, 116, 240, 220, 40, 241, 82, 228, 209, 57, 128, 152, 9, 144, 112,
362 249, 48, 46, 135, 182, 250, 59, 135, 221, 129, 46, 204, 178, 232, 100, 172, 27, 177, 120, 86, 253, 35, 137,
363 19, 253, 191, 202, 97, 240, 10, 45, 124, 110, 234, 149, 49, 115, 209, 177, 153, 231, 93, 211, 214, 19, 127,
364 143, 103, 47, 239, 86, 73, 91, 231, 94, 248, 143, 54, 54, 190, 51, 47, 136, 92, 157, 13, 226, 13, 96, 104,
365 159, 17, 206, 66, 25, 157, 51, 5, 252, 166, 135, 213, 118, 107, 152, 226, 253, 51, 136, 74, 186, 52, 64,
366 236, 152, 115, 0, 29, 23, 247, 3, 20, 124, 21, 116,
367 ];
368 assert_eq!(buf_out, buf_out_expected);
369 }
370
371 #[cfg(not(feature = "alloc"))]
372 #[test]
373 fn lc3_encode_channel() {
374 const NUM_CH: usize = 1;
375 const DURATION: FrameDuration = FrameDuration::TenMs;
376 const FREQ: SamplingFrequency = SamplingFrequency::Hz48000;
377 const BUF_LENGTHS: (usize, usize, usize) = Lc3Encoder::<NUM_CH>::calc_working_buffer_lengths(DURATION, FREQ);
378 let mut integer_buf = [0; BUF_LENGTHS.0];
379 let mut scaler_buf = [0.0; BUF_LENGTHS.1];
380 let mut complex_buf = [Complex::default(); BUF_LENGTHS.2];
381
382 let mut encoder =
383 Lc3Encoder::<NUM_CH>::new(DURATION, FREQ, &mut integer_buf, &mut scaler_buf, &mut complex_buf);
384 let samples_in = [
385 836, 739, 638, 510, 352, 200, 72, -56, -177, -297, -416, -520, -623, -709, -791, -911, -1062, -1199, -1298,
386 -1375, -1433, -1484, -1548, -1603, -1648, -1687, -1724, -1744, -1730, -1699, -1650, -1613, -1594, -1563,
387 -1532, -1501, -1473, -1441, -1409, -1393, -1355, -1280, -1201, -1118, -1032, -953, -860, -741, -613, -477,
388 -355, -261, -168, -80, -8, 57, 127, 217, 296, 347, 385, 413, 456, 517, 575, 640, 718, 806, 888, 963, 1041,
389 1080, 1081, 1083, 1072, 1062, 1067, 1056, 1035, 1019, 999, 964, 934, 909, 876, 854, 835, 813, 795, 781,
390 783, 772, 750, 747, 728, 713, 726, 716, 680, 638, 580, 516, 451, 393, 351, 307, 244, 161, 79, 18, -45,
391 -123, -215, -301, -389, -512, -644, -764, -888, -1006, -1126, -1253, -1378, -1500, -1614, -1716, -1813,
392 -1926, -2051, -2176, -2301, -2416, -2514, -2595, -2680, -2783, -2883, -2977, -3068, -3163, -3262, -3341,
393 -3381, -3392, -3392, -3379, -3368, -3353, -3318, -3292, -3244, -3169, -3109, -3049, -2989, -2922, -2844,
394 -2790, -2743, -2672, -2588, -2490, -2371, -2222, -2046, -1861, -1695, -1546, -1384, -1214, -1058, -913,
395 -761, -602, -441, -280, -124, 24, 169, 302, 421, 546, 661, 738, 796, 851, 924, 1055, 1227, 1412, 1588,
396 1707, 1787, 1853, 1905, 1963, 2015, 2048, 2072, 2082, 2093, 2099, 2095, 2097, 2086, 2063, 2060, 2069, 2052,
397 2012, 1977, 1956, 1948, 1918, 1843, 1748, 1641, 1533, 1435, 1342, 1252, 1163, 1081, 1024, 989, 962, 937,
398 911, 879, 841, 769, 657, 541, 445, 365, 289, 202, 104, -4, -119, -245, -381, -523, -655, -770, -874, -957,
399 -1017, -1069, -1118, -1173, -1256, -1370, -1497, -1629, -1745, -1827, -1882, -1934, -2021, -2115, -2165,
400 -2196, -2230, -2258, -2282, -2302, -2320, -2332, -2340, -2344, -2338, -2313, -2269, -2215, -2152, -2072,
401 -1978, -1885, -1793, -1704, -1621, -1528, -1419, -1310, -1213, -1116, -1014, -914, -820, -736, -656, -578,
402 -514, -445, -358, -276, -206, -136, -62, 0, 56, 124, 190, 253, 316, 379, 458, 552, 630, 686, 725, 735, 709,
403 661, 612, 572, 538, 507, 476, 453, 448, 453, 444, 415, 370, 316, 257, 203, 159, 125, 107, 114, 137, 162,
404 181, 189, 186, 166, 145, 145, 154, 154, 161, 184, 200, 217, 254, 294, 325, 332, 320, 302, 286, 273, 260,
405 266, 294, 297, 274, 251, 221, 170, 100, 29, -31, -82, -134, -187, -232, -278, -347, -426, -490, -548, -613,
406 -677, -727, -755, -769, -770, -757, -741, -729, -713, -684, -659, -647, -631, -606, -588, -585, -577, -555,
407 -534, -527, -528, -513, -480, -456, -440, -415, -382, -333, -244, -132, -32, 47, 130, 225, 308, 383, 460,
408 533, 607, 687, 757, 817, 889, 977, 1038, 1064, 1100, 1165, 1250, 1349, 1456, 1563, 1665, 1755, 1829, 1890,
409 1935, 1973, 2008, 2033, 2044, 2054, 2076, 2106, 2125, 2115, 2097, 2092, 2093, 2082, 2067, 2068, 2095, 2135,
410 2169, 2193, 2213, 2219, 2202, 2163, 2101, 2033, 1992, 1985, 1990, 1986, 1978, 1977, 1976, 1969, 1959, 1956,
411 1960, 1955, 1930, 1907, 1884, 1844, 1790, 1733, 1687, 1649, 1611, 1586,
412 ];
413 let mut buf_out = [0; 150];
414
415 encoder.encode_frame(0, &samples_in, &mut buf_out).unwrap();
416
417 let buf_out_expected = [
418 230, 243, 160, 169, 152, 75, 36, 156, 223, 96, 241, 214, 150, 248, 180, 106, 115, 92, 147, 213, 56, 100,
419 96, 52, 194, 178, 44, 31, 222, 246, 83, 116, 240, 220, 40, 241, 82, 228, 209, 57, 128, 152, 9, 144, 112,
420 249, 48, 46, 135, 182, 250, 59, 135, 221, 129, 46, 204, 178, 232, 100, 172, 27, 177, 120, 86, 253, 35, 137,
421 19, 253, 191, 202, 97, 240, 10, 45, 124, 110, 234, 149, 49, 115, 209, 177, 153, 231, 93, 211, 214, 19, 127,
422 143, 103, 47, 239, 86, 73, 91, 231, 94, 248, 143, 54, 54, 190, 51, 47, 136, 92, 157, 13, 226, 13, 96, 104,
423 159, 17, 206, 66, 25, 157, 51, 5, 252, 166, 135, 213, 118, 107, 152, 226, 253, 51, 136, 74, 186, 52, 64,
424 236, 152, 115, 0, 29, 23, 247, 3, 20, 124, 21, 116,
425 ];
426 assert_eq!(buf_out, buf_out_expected);
427 }
428}