]> git.nihav.org Git - nihav.git/blob - nihav-realmedia/src/codecs/ra288.rs
1774ff571cb7588864b786cb7983c5e3898ee2af
[nihav.git] / nihav-realmedia / src / codecs / ra288.rs
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;
9
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;
14
15 struct RA288Decoder {
16 chmap: NAChannelMap,
17 ainfo: NAAudioInfo,
18 info: NACodecInfoRef,
19
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],
26 }
27
28 const BF_ORDER: usize = SP_LPC_ORDER + 1;
29 const BF_WORK_SIZE: usize = SP_LPC_ORDER + 40 + 35;
30
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();
35
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];
41 }
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);
47 }
48
49 for i in 0..=order {
50 rec[i] = rec[i] * 0.5625 + tmp1[i];
51 temp[i] = rec[i] + tmp2[i];
52 }
53 temp[0] *= 257.0 / 256.0;
54
55 if compute_lpc(&temp, filt) {
56 for (f, c) in filt.iter_mut().zip(bw_tab.iter()) {
57 *f *= c;
58 }
59 }
60 for i in 0..move_size {
61 hist[i] = hist[i + start];
62 }
63 }
64
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)) {
68 sum += *a * *b;
69 }
70 sum
71 }
72
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) {
77 return false;
78 }
79 for i in 0..order {
80 let mut r = -autoc[i + 1];
81 for j in 0..i {
82 r -= filt[j] * autoc[i - j];
83 }
84 r /= err;
85 err *= 1.0 - r * r;
86 filt[i] = r;
87
88 for j in 0..((i + 1) >> 1) {
89 let f = filt[j];
90 let b = filt[i - j - 1];
91 filt[j] = f + r * b;
92 filt[i - j - 1] = b + r * f;
93 }
94
95 if err < 0.0 { return false; }
96 }
97 true
98 }
99
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];
105 }
106 }
107 }
108
109 impl RA288Decoder {
110 fn new() -> Self {
111 RA288Decoder {
112 chmap: NAChannelMap::new(),
113 ainfo: NAAudioInfo::new(0, 1, SND_F32P_FORMAT, NBLOCKS * BLOCKSIZE),
114 info: NACodecInfo::new_dummy(),
115
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],
122 }
123 }
124
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];
128 }
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)
132 .max(0.0).min(60.0);
133
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;
138 }
139
140 let mut sum: f32 = 0.0;
141 for el in buf.iter() {
142 sum += *el * *el * (((1 << 24) as f32) / 5.0);
143 }
144 sum = sum.max(1.0);
145 for i in 0..(GAIN_LPC_ORDER - 1) {
146 self.gain_hist[GAIN_START + i] = self.gain_hist[GAIN_START + i + 1];
147 }
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);
150 }
151 }
152
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(),
158 1,
159 SND_F32P_FORMAT, NBLOCKS * BLOCKSIZE);
160 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo));
161 Ok(())
162 } else {
163 Err(DecoderError::InvalidData)
164 }
165 }
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;
172
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();
176
177 for (input, output) in pktbuf.chunks(FRAME_SIZE).zip(dst.chunks_mut(NBLOCKS * BLOCKSIZE)) {
178 let mut br = BitReader::new(input, BitReaderMode::LE);
179
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;
183
184 self.process_subblock(gain, cb);
185
186 block.copy_from_slice(&self.speech_hist[SP_START + SP_LPC_ORDER..][..BLOCKSIZE]);
187 if (i & 7) == 3 {
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);
190 }
191 }
192 }
193
194 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
195 frm.set_keyframe(true);
196 Ok(frm.into_ref())
197 }
198 fn flush(&mut self) {
199 }
200 }
201
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 }
206 }
207
208 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
209 Box::new(RA288Decoder::new())
210 }
211
212 #[cfg(test)]
213 mod test {
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;
219 #[test]
220 fn test_ra288() {
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);
225
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);
229 }
230 }
231
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
235 ];
236
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]
302 ];
303
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
324 ];
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
332 ];
333
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
342 ];
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
346 ];