lc3_codec/encoder/
lc3_encoder.rs

1// Copyright 2022 David Haig
2// Licensed under the Apache License, Version 2.0 (the "License");
3
4// If the `alloc` feature is enabled (which it is by default) then the
5// Lc3Encoder can be initialised dynamically (with variable inputs not known at compile time)
6// However, if the `alloc` feature is not enabled (e.g. with `default-features = false`) then
7// the Lc3Encoder will be initialised statically with constants like number of channels specified
8// at compile time. This suits microcontroller environments.
9// There should be no performance difference between using alloc and not because memory is preallocated
10// before the encoder starts using it and the same memory gets used over and over again.
11
12#[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/// Main entry point of library - Start here for the Encoder
28
29#[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    // scratch buffers used anew for every frame (data from previous frames in these buffers is overwritten)
56    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        // modified discrete cosine transform (mutates output and energy_bands)
68        let near_nyquist_flag = self.mdct.run(x_s, self.mdct_out, self.energy_bands);
69
70        // NOTE: the mdct above takes output[..nf] and transforms it to output[..ne] (e.g. 480 => 400)
71        let (spec_lines, _) = self.mdct_out.split_at_mut(self.config.ne);
72
73        // bandwidth detector
74        let bandwidth = self.bandwidth_detector.run(self.energy_bands);
75
76        // attack detector
77        let attack_detected = self.attack_detector.run(x_s, buf_out.len());
78
79        // spectral noise shaping
80        let sns = self
81            .spectral_noise_shaping
82            .run(spec_lines, self.energy_bands, attack_detected);
83
84        // temporal noise shaping
85        let tns = self
86            .temporal_noise_shaping
87            .run(spec_lines, bandwidth.bandwidth_ind, nbits, near_nyquist_flag);
88
89        // long term post filter - half the time spent here
90        let post_filter = self.long_term_post_filter.run(x_s, near_nyquist_flag, nbits);
91
92        // spectral quantization
93        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        // residual bits
98        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        // noise level estimation
103        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    // (integer, scaler, complex)
194    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    // (integer, scaler, complex)
289    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}