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