]> git.nihav.org Git - nihav.git/blame - nihav-realmedia/src/codecs/ra288.rs
avimux: do not record palette change chunks in OpenDML index
[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
d92111a8 31#[allow(clippy::too_many_arguments)]
37d2275e
KS
32fn 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 }
e07387c7 42 for i in (0..=order).rev() {
37d2275e
KS
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
e07387c7 49 for i in 0..=order {
37d2275e
KS
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
65fn 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
73fn 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
100fn 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
109impl 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 }
d92111a8
KS
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);
37d2275e
KS
133
134 let scale = (sum * 0.1151292546497).exp() * gain * (1.0 / ((1 << 23) as f32));
135 let mut buf: [f32; BLOCKSIZE] = [0.0; BLOCKSIZE];
d92111a8
KS
136 for (dst, &cb) in buf.iter_mut().zip(RA288_CODEBOOK[cb_idx].iter()) {
137 *dst = (cb as f32) * scale;
37d2275e
KS
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
d92111a8 186 block.copy_from_slice(&self.speech_hist[SP_START + SP_LPC_ORDER..][..BLOCKSIZE]);
37d2275e
KS
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);
171860fc 196 Ok(frm.into_ref())
37d2275e 197 }
f9be4e75
KS
198 fn flush(&mut self) {
199 }
37d2275e
KS
200}
201
7d57ae2f
KS
202impl 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
08a1fab7 208pub fn get_decoder() -> Box<dyn NADecoder + Send> {
37d2275e
KS
209 Box::new(RA288Decoder::new())
210}
211
212#[cfg(test)]
213mod test {
3167c45c
KS
214 use nihav_core::codecs::RegisteredDecoders;
215 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 216 use nihav_codec_support::test::dec_video::*;
78fb6560 217 use crate::realmedia_register_all_decoders;
e64739f8 218 use crate::realmedia_register_all_demuxers;
37d2275e
KS
219 #[test]
220 fn test_ra288() {
3167c45c
KS
221 let mut dmx_reg = RegisteredDemuxers::new();
222 realmedia_register_all_demuxers(&mut dmx_reg);
223 let mut dec_reg = RegisteredDecoders::new();
78fb6560 224 realmedia_register_all_decoders(&mut dec_reg);
3167c45c 225
886cde48 226 // sample: https://samples.mplayerhq.hu/real/AC-28_8/A0000044.rm
37d2275e 227 let file = "assets/RV/A0000044.rm";
5580b11b 228 test_decode_audio("realmedia", file, Some(5000), None/*Some("ra28.8")*/, &dmx_reg, &dec_reg);
37d2275e
KS
229 }
230}
231
232const 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
237const 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
304const 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];
325const 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
334const 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];
343const 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];