1 use nihav_core::formats::*;
2 use nihav_core::frame::*;
3 use nihav_core::codecs::*;
4 use nihav_core::io::bitreader::*;
5 const CHMAP_MONO: [NAChannelType; 1] = [NAChannelType::C];
6 const NBLOCKS: usize = 32;
7 const BLOCKSIZE: usize = 5;
8 const FRAME_SIZE: usize = 38;
10 const SP_LPC_ORDER: usize = 36;
11 const SP_START: usize = 70;
12 const GAIN_LPC_ORDER: usize = 10;
13 const GAIN_START: usize = 28;
20 speech_lpc: [f32; SP_LPC_ORDER],
21 speech_hist: [f32; 111],
22 speech_rec: [f32; SP_LPC_ORDER + 1],
23 gain_lpc: [f32; GAIN_LPC_ORDER],
24 gain_hist: [f32; GAIN_LPC_ORDER + GAIN_START],
25 gain_rec: [f32; GAIN_LPC_ORDER + 1],
28 const BF_ORDER: usize = SP_LPC_ORDER + 1;
29 const BF_WORK_SIZE: usize = SP_LPC_ORDER + 40 + 35;
31 #[allow(clippy::too_many_arguments)]
32 fn backfilter(hist: &mut [f32], rec: &mut [f32], filt: &mut [f32], win: &[f32], bw_tab: &[f32], start: usize, non_rec: usize, move_size: usize) {
33 let mut temp: [f32; BF_ORDER] = [0.0; BF_ORDER];
34 let order = filt.len();
36 let mut tmp1: [f32; BF_ORDER] = [0.0; BF_ORDER];
37 let mut tmp2: [f32; BF_ORDER] = [0.0; BF_ORDER];
38 let mut work: [f32; BF_WORK_SIZE] = [0.0; BF_WORK_SIZE];
39 for i in 0..(order + start + non_rec) {
40 work[i] = win[i] * hist[i];
42 for i in (0..=order).rev() {
43 let src1 = &work[(order - i)..];
44 let src2 = &work[order + start - i..];
45 tmp1[i] = scalarprod(&work[order..], src1, start);
46 tmp2[i] = scalarprod(&work[order + start..], src2, non_rec);
50 rec[i] = rec[i] * 0.5625 + tmp1[i];
51 temp[i] = rec[i] + tmp2[i];
53 temp[0] *= 257.0 / 256.0;
55 if compute_lpc(&temp, filt) {
56 for (f, c) in filt.iter_mut().zip(bw_tab.iter()) {
60 for i in 0..move_size {
61 hist[i] = hist[i + start];
65 fn scalarprod(src0: &[f32], src1: &[f32], len: usize) -> f32 {
66 let mut sum: f32 = 0.0;
67 for (a, b) in src0.iter().take(len).zip(src1.iter().take(len)) {
73 fn compute_lpc(autoc: &[f32], filt: &mut [f32]) -> bool {
74 let order = filt.len();
75 let mut err = autoc[0];
76 if (err <= 0.0) || (autoc[order] == 0.0) {
80 let mut r = -autoc[i + 1];
82 r -= filt[j] * autoc[i - j];
88 for j in 0..((i + 1) >> 1) {
90 let b = filt[i - j - 1];
92 filt[i - j - 1] = b + r * f;
95 if err < 0.0 { return false; }
100 fn celp_lp_synth_filter(dst: &mut [f32], start: usize, filt: &[f32], src: &[f32]) {
101 for (i, el) in src.iter().enumerate() {
102 dst[start + i] = *el;
103 for (j, coeff) in filt.iter().enumerate() {
104 dst[start + i] -= *coeff * dst[start + i - j - 1];
112 chmap: NAChannelMap::new(),
113 ainfo: NAAudioInfo::new(0, 1, SND_F32P_FORMAT, NBLOCKS * BLOCKSIZE),
114 info: NACodecInfo::new_dummy(),
116 speech_lpc: [0.0; SP_LPC_ORDER],
117 speech_hist: [0.0; 111],
118 speech_rec: [0.0; SP_LPC_ORDER + 1],
119 gain_lpc: [0.0; GAIN_LPC_ORDER],
120 gain_hist: [0.0; 38],
121 gain_rec: [0.0; GAIN_LPC_ORDER + 1],
125 fn process_subblock(&mut self, gain: f32, cb_idx: usize) {
126 for i in 0..SP_LPC_ORDER {
127 self.speech_hist[SP_START + i] = self.speech_hist[75 + i];
129 let sum = self.gain_hist[GAIN_START..].iter().rev()
130 .zip(self.gain_lpc.iter())
131 .fold(32.0f32, |acc, (&a, &b)| acc - a * b)
134 let scale = (sum * 0.1151292546497).exp() * gain * (1.0 / ((1 << 23) as f32));
135 let mut buf: [f32; BLOCKSIZE] = [0.0; BLOCKSIZE];
136 for (dst, &cb) in buf.iter_mut().zip(RA288_CODEBOOK[cb_idx].iter()) {
137 *dst = (cb as f32) * scale;
140 let mut sum: f32 = 0.0;
141 for el in buf.iter() {
142 sum += *el * *el * (((1 << 24) as f32) / 5.0);
145 for i in 0..(GAIN_LPC_ORDER - 1) {
146 self.gain_hist[GAIN_START + i] = self.gain_hist[GAIN_START + i + 1];
148 self.gain_hist[GAIN_START + GAIN_LPC_ORDER - 1] = 10.0 * sum.log10() - 32.0;
149 celp_lp_synth_filter(&mut self.speech_hist, SP_START + SP_LPC_ORDER, &self.speech_lpc, &buf);
153 impl NADecoder for RA288Decoder {
154 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
155 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
156 self.chmap.add_channels(&CHMAP_MONO);
157 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(),
159 SND_F32P_FORMAT, NBLOCKS * BLOCKSIZE);
160 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo));
163 Err(DecoderError::InvalidData)
166 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
167 let info = pkt.get_stream().get_info();
168 validate!(info.get_properties().is_audio());
169 let pktbuf = pkt.get_buffer();
170 let nframes = pktbuf.len() / FRAME_SIZE;
171 let duration = NBLOCKS * BLOCKSIZE * nframes;
173 let abuf = alloc_audio_buffer(self.ainfo, duration, self.chmap.clone())?;
174 let mut adata = abuf.get_abuf_f32().unwrap();
175 let dst = adata.get_data_mut().unwrap();
177 for (input, output) in pktbuf.chunks(FRAME_SIZE).zip(dst.chunks_mut(NBLOCKS * BLOCKSIZE)) {
178 let mut br = BitReader::new(input, BitReaderMode::LE);
180 for (i, block) in output.chunks_mut(BLOCKSIZE).enumerate() {
181 let gain = RA288_GAIN_TAB[br.read(3)? as usize];
182 let cb = br.read((6 + (i & 1)) as u8)? as usize;
184 self.process_subblock(gain, cb);
186 block.copy_from_slice(&self.speech_hist[SP_START + SP_LPC_ORDER..][..BLOCKSIZE]);
188 backfilter(&mut self.speech_hist, &mut self.speech_rec, &mut self.speech_lpc, RA288_SPEECH_WINDOW, RA288_SPEECH_BW_TAB, 40, 35, SP_START);
189 backfilter(&mut self.gain_hist, &mut self.gain_rec, &mut self.gain_lpc, RA288_GAIN_WINDOW, RA288_GAIN_BW_TAB, 8, 20, GAIN_START);
194 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
195 frm.set_keyframe(true);
198 fn flush(&mut self) {
202 impl NAOptionHandler for RA288Decoder {
203 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
204 fn set_options(&mut self, _options: &[NAOption]) { }
205 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
208 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
209 Box::new(RA288Decoder::new())
214 use nihav_core::codecs::RegisteredDecoders;
215 use nihav_core::demuxers::RegisteredDemuxers;
216 use nihav_codec_support::test::dec_video::*;
217 use crate::realmedia_register_all_decoders;
218 use crate::realmedia_register_all_demuxers;
221 let mut dmx_reg = RegisteredDemuxers::new();
222 realmedia_register_all_demuxers(&mut dmx_reg);
223 let mut dec_reg = RegisteredDecoders::new();
224 realmedia_register_all_decoders(&mut dec_reg);
226 // sample: https://samples.mplayerhq.hu/real/AC-28_8/A0000044.rm
227 let file = "assets/RV/A0000044.rm";
228 test_decode_audio("realmedia", file, Some(5000), None/*Some("ra28.8")*/, &dmx_reg, &dec_reg);
232 const RA288_GAIN_TAB: [f32; 8] = [
233 0.515625, 0.90234375, 1.57910156, 2.76342773,
234 -0.515625, -0.90234375, -1.57910156, -2.76342773
237 const RA288_CODEBOOK: [[i16; 5]; 128] = [
238 [ 668, -2950, -1254, -1790, -2553], [ -5032, -4577, -1045, 2908, 3318],
239 [ -2819, -2677, -948, -2825, -4450], [ -6679, -340, 1482, -1276, 1262],
240 [ -562, -6757, 1281, 179, -1274], [ -2512, -7130, -4925, 6913, 2411],
241 [ -2478, -156, 4683, -3873, 0], [ -8208, 2140, -478, -2785, 533],
242 [ 1889, 2759, 1381, -6955, -5913], [ 5082, -2460, -5778, 1797, 568],
243 [ -2208, -3309, -4523, -6236, -7505], [ -2719, 4358, -2988, -1149, 2664],
244 [ 1259, 995, 2711, -2464,-10390], [ 1722, -7569, -2742, 2171, -2329],
245 [ 1032, 747, -858, -7946,-12843], [ 3106, 4856, -4193, -2541, 1035],
246 [ 1862, -960, -6628, 410, 5882], [ -2493, -2628, -4000, -60, 7202],
247 [ -2672, 1446, 1536, -3831, 1233], [ -5302, 6912, 1589, -4187, 3665],
248 [ -3456, -8170, -7709, 1384, 4698], [ -4699, -6209,-11176, 8104, 16830],
249 [ 930, 7004, 1269, -8977, 2567], [ 4649, 11804, 3441, -5657, 1199],
250 [ 2542, -183, -8859, -7976, 3230], [ -2872, -2011, -9713, -8385, 12983],
251 [ 3086, 2140, -3680, -9643, -2896], [ -7609, 6515, -2283, -2522, 6332],
252 [ -3333, -5620, -9130,-11131, 5543], [ -407, -6721,-17466, -2889, 11568],
253 [ 3692, 6796, -262,-10846, -1856], [ 7275, 13404, -2989,-10595, 4936],
254 [ 244, -2219, 2656, 3776, -5412], [ -4043, -5934, 2131, 863, -2866],
255 [ -3302, 1743, -2006, -128, -2052], [ -6361, 3342, -1583, -21, 1142],
256 [ -3837, -1831, 6397, 2545, -2848], [ -9332, -6528, 5309, 1986, -2245],
257 [ -4490, 748, 1935, -3027, -493], [ -9255, 5366, 3193, -4493, 1784],
258 [ 4784, -370, 1866, 1057, -1889], [ 7342, -2690, -2577, 676, -611],
259 [ -502, 2235, -1850, -1777, -2049], [ 1011, 3880, -2465, 2209, -152],
260 [ 2592, 2829, 5588, 2839, -7306], [ -3049, -4918, 5955, 9201, -4447],
261 [ 697, 3908, 5798, -4451, -4644], [ -2121, 5444, -2570, 321, -1202],
262 [ 2846, -2086, 3532, 566, -708], [ -4279, 950, 4980, 3749, 452],
263 [ -2484, 3502, 1719, -170, 238], [ -3435, 263, 2114, -2005, 2361],
264 [ -7338, -1208, 9347, -1216, -4013], [-13498, -439, 8028, -4232, 361],
265 [ -3729, 5433, 2004, -4727, -1259], [ -3986, 7743, 8429, -3691, -987],
266 [ 5198, -423, 1150, -1281, 816], [ 7409, 4109, -3949, 2690, 30],
267 [ 1246, 3055, -35, -1370, -246], [ -1489, 5635, -678, -2627, 3170],
268 [ 4830, -4585, 2008, -1062, 799], [ -129, 717, 4594, 14937, 10706],
269 [ 417, 2759, 1850, -5057, -1153], [ -3887, 7361, -5768, 4285, 666],
270 [ 1443, -938, 20, -2119, -1697], [ -3712, -3402, -2212, 110, 2136],
271 [ -2952, 12, -1568, -3500, -1855], [ -1315, -1731, 1160, -558, 1709],
272 [ 88, -4569, 194, -454, -2957], [ -2839, -1666, -273, 2084, -155],
273 [ -189, -2376, 1663, -1040, -2449], [ -2842, -1369, 636, -248, -2677],
274 [ 1517, 79, -3013, -3669, -973], [ 1913, -2493, -5312, -749, 1271],
275 [ -2903, -3324, -3756, -3690, -1829], [ -2913, -1547, -2760, -1406, 1124],
276 [ 1844, -1834, 456, 706, -4272], [ 467, -4256, -1909, 1521, 1134],
277 [ -127, -994, -637, -1491, -6494], [ 873, -2045, -3828, -2792, -578],
278 [ 2311, -1817, 2632, -3052, 1968], [ 641, 1194, 1893, 4107, 6342],
279 [ -45, 1198, 2160, -1449, 2203], [ -2004, 1713, 3518, 2652, 4251],
280 [ 2936, -3968, 1280, 131, -1476], [ 2827, 8, -1928, 2658, 3513],
281 [ 3199, -816, 2687, -1741, -1407], [ 2948, 4029, 394, -253, 1298],
282 [ 4286, 51, -4507, -32, -659], [ 3903, 5646, -5588, -2592, 5707],
283 [ -606, 1234, -1607, -5187, 664], [ -525, 3620, -2192, -2527, 1707],
284 [ 4297, -3251, -2283, 812, -2264], [ 5765, 528, -3287, 1352, 1672],
285 [ 2735, 1241, -1103, -3273, -3407], [ 4033, 1648, -2965, -1174, 1444],
286 [ 74, 918, 1999, 915, -1026], [ -2496, -1605, 2034, 2950, 229],
287 [ -2168, 2037, 15, -1264, -208], [ -3552, 1530, 581, 1491, 962],
288 [ -2613, -2338, 3621, -1488, -2185], [ -1747, 81, 5538, 1432, -2257],
289 [ -1019, 867, 214, -2284, -1510], [ -1684, 2816, -229, 2551, -1389],
290 [ 2707, 504, 479, 2783, -1009], [ 2517, -1487, -1596, 621, 1929],
291 [ -148, 2206, -4288, 1292, -1401], [ -527, 1243, -2731, 1909, 1280],
292 [ 2149, -1501, 3688, 610, -4591], [ 3306, -3369, 1875, 3636, -1217],
293 [ 2574, 2513, 1449, -3074, -4979], [ 814, 1826, -2497, 4234, -4077],
294 [ 1664, -220, 3418, 1002, 1115], [ 781, 1658, 3919, 6130, 3140],
295 [ 1148, 4065, 1516, 815, 199], [ 1191, 2489, 2561, 2421, 2443],
296 [ 770, -5915, 5515, -368, -3199], [ 1190, 1047, 3742, 6927, -2089],
297 [ 292, 3099, 4308, -758, -2455], [ 523, 3921, 4044, 1386, 85],
298 [ 4367, 1006, -1252, -1466, -1383], [ 3852, 1579, -77, 2064, 868],
299 [ 5109, 2919, -202, 359, -509], [ 3650, 3206, 2303, 1693, 1296],
300 [ 2905, -3907, 229, -1196, -2332], [ 5977, -3585, 805, 3825, -3138],
301 [ 3746, -606, 53, -269, -3301], [ 606, 2018, -1316, 4064, 398]
304 const RA288_SPEECH_WINDOW: &[f32] = &[
305 0.576690972, 0.580838025, 0.585013986, 0.589219987, 0.59345597, 0.597723007,
306 0.602020264, 0.606384277, 0.610748291, 0.615142822, 0.619598389, 0.624084473,
307 0.628570557, 0.633117676, 0.637695313, 0.642272949, 0.646911621, 0.651580811,
308 0.656280518, 0.66104126, 0.665802002, 0.670593262, 0.675445557, 0.680328369,
309 0.685241699, 0.690185547, 0.695159912, 0.700164795, 0.705230713, 0.710327148,
310 0.715454102, 0.720611572, 0.725830078, 0.731048584, 0.736328125, 0.741638184,
311 0.747009277, 0.752380371, 0.7578125, 0.763305664, 0.768798828, 0.774353027,
312 0.779937744, 0.785583496, 0.791229248, 0.796936035, 0.802703857, 0.808502197,
313 0.814331055, 0.820220947, 0.826141357, 0.832092285, 0.838104248, 0.844146729,
314 0.850250244, 0.856384277, 0.862548828, 0.868774414, 0.875061035, 0.881378174,
315 0.88772583, 0.894134521, 0.900604248, 0.907104492, 0.913635254, 0.920227051,
316 0.926879883, 0.933563232, 0.940307617, 0.94708252, 0.953918457, 0.96081543,
317 0.96774292, 0.974731445, 0.981781006, 0.988861084, 0.994842529, 0.998565674,
318 0.999969482, 0.99911499, 0.996002197, 0.990600586, 0.982910156, 0.973022461,
319 0.960876465, 0.946533203, 0.930053711, 0.911437988, 0.89074707, 0.868041992,
320 0.843322754, 0.816680908, 0.788208008, 0.757904053, 0.725891113, 0.692199707,
321 0.656921387, 0.620178223, 0.582000732, 0.542480469, 0.501739502, 0.459838867,
322 0.416900635, 0.373016357, 0.328277588, 0.282775879, 0.236663818, 0.189971924,
323 0.142852783, 0.0954284668,0.0477600098
325 const RA288_SPEECH_BW_TAB: &[f32] = &[
326 0.98828125, 0.976699829, 0.965254128, 0.953942537, 0.942763507, 0.931715488,
327 0.920796931, 0.910006344, 0.899342179, 0.888803005, 0.878387332, 0.868093729,
328 0.857920766, 0.847867012, 0.837931097, 0.828111589, 0.818407178, 0.808816493,
329 0.799338162, 0.789970934, 0.780713439, 0.771564424, 0.762522638, 0.753586829,
330 0.744755745, 0.736028135, 0.727402806, 0.718878567, 0.710454226, 0.702128589,
331 0.693900526, 0.685768902, 0.677732527, 0.669790328, 0.66194123, 0.654184103
334 const RA288_GAIN_WINDOW: &[f32] = &[
335 0.505699992, 0.524200022, 0.54339999, 0.563300014, 0.583953857, 0.60534668,
336 0.627502441, 0.650482178, 0.674316406, 0.699005127, 0.724578857, 0.75112915,
337 0.778625488, 0.807128906, 0.836669922, 0.86730957, 0.899078369, 0.932006836,
338 0.961486816, 0.982757568, 0.995635986, 1.0, 0.995819092, 0.983154297,
339 0.96206665, 0.932769775, 0.895507813, 0.850585938, 0.798400879, 0.739379883,
340 0.674072266, 0.602996826, 0.526763916, 0.446014404, 0.361480713, 0.273834229,
341 0.183868408, 0.0923461914
343 const RA288_GAIN_BW_TAB: &[f32] = &[
344 0.90625, 0.821289063, 0.74432373, 0.674499512, 0.61126709,
345 0.553955078, 0.50201416, 0.454956055, 0.41229248, 0.373657227