ape: move dotproduct+filter adaptation into a separate function
[nihav.git] / nihav-llaudio / src / codecs / apepred.rs
CommitLineData
87927c57
KS
1const HISTORY_SIZE: usize = 512;
2
3fn val2sign(val: i32) -> i32 {
4 if val > 0 {
5 -1
6 } else if val < 0 {
7 1
8 } else {
9 0
10 }
11}
12
13pub struct OldFilt {
14 version: u16,
15 compression: u16,
16}
17
18pub struct NewFilt {
19 version: u16,
20 filters: [NFilterContext; 3],
21 lfilt: LastFilterContext,
22 rfilt: LastFilterContext,
23}
24
25#[allow(clippy::large_enum_variant)]
26pub enum FilterMode {
27 Old(OldFilt),
28 New(NewFilt),
29 None,
30}
31
32impl FilterMode {
33 pub fn new(version: u16, compression: u16) -> Self {
34 if version < 3930 {
35 FilterMode::Old(OldFilt::new(version, compression))
36 } else {
37 FilterMode::New(NewFilt::new(version, compression))
38 }
39 }
40 pub fn filter_mono(&mut self, l: &mut [i32]) {
41 match *self {
42 FilterMode::Old(ref mut ofilt) => ofilt.filter(l),
43 FilterMode::New(ref mut nfilt) => nfilt.filter_mono(l),
44 FilterMode::None => unreachable!(),
45 };
46 }
47 pub fn filter_stereo(&mut self, l: &mut [i32], r: &mut [i32]) {
48 match *self {
49 FilterMode::Old(ref mut ofilt) => {
50 ofilt.filter(l);
51 ofilt.filter(r);
52 for (l, r) in l.iter_mut().zip(r.iter_mut()) {
53 let new_l = *l - *r / 2;
54 let new_r = *r + new_l;
55 *l = new_l;
56 *r = new_r;
57 }
58 },
59 FilterMode::New(ref mut nfilt) => {
60 nfilt.filter_stereo(l, r);
61 for (l, r) in l.iter_mut().zip(r.iter_mut()) {
62 let new_l = *r - *l / 2;
63 let new_r = *l + new_l;
64 *l = new_l;
65 *r = new_r;
66 }
67 },
68 FilterMode::None => unreachable!(),
69 };
70 }
71}
72
73const NEW_FILTER_PARAMS: [[(u8, u8); 3]; 5] = [
74 [ (0, 0), ( 0, 0), ( 0, 0) ],
75 [ (1, 11), ( 0, 0), ( 0, 0) ],
76 [ (4, 11), ( 0, 0), ( 0, 0) ],
77 [ (2, 10), (16, 13), ( 0, 0) ],
78 [ (1, 11), (16, 13), (80, 15) ],
79];
80
81#[derive(Clone,Default)]
82struct NFilterContext {
83 buf: Vec<i32>,
84 coeffs: Vec<i32>,
85 order: usize,
86 bits: u8,
87 avg: i32,
88 new: bool,
89}
90
d33a2721
KS
91fn adapt_loop(filt: &mut [i32], coeffs: &[i32], adapt: &[i32], val: i32) -> i32 {
92 let mut sum = 0i32;
93 for (coef, (res, adapt)) in filt.iter_mut().zip(coeffs.iter().zip(adapt.iter())) {
94 sum += *coef * *res;
95 if val < 0 {
96 *coef += *adapt;
97 } else if val > 0 {
98 *coef -= *adapt;
99 }
100 }
101 sum
102}
103
87927c57
KS
104impl NFilterContext {
105 fn new(ord16: u8, bits: u8, new: bool) -> Self {
106 let order = ord16 as usize * 16;
107 Self {
108 buf: if order > 0 { vec![0; order * 2 + HISTORY_SIZE] } else { Vec::new() },
109 coeffs: vec![0; order],
110 order,
111 bits,
112 avg: 0,
113 new,
114 }
115 }
116 fn reset(&mut self) {
117 for el in self.buf[..self.order * 2].iter_mut() { *el = 0; }
118 for el in self.coeffs.iter_mut() { *el = 0; }
119 self.avg = 0;
120 }
121 fn apply(&mut self, dst: &mut [i32]) {
122 if self.order == 0 { return; }
123 let mut adapt_pos = self.order;
124 let mut delay_pos = self.order * 2;
125 for el in dst.iter_mut() {
d33a2721
KS
126 let sum = adapt_loop(&mut self.coeffs,
127 &self.buf[delay_pos - self.order..],
128 &self.buf[adapt_pos - self.order..], *el);
87927c57
KS
129 let pred = (sum + (1 << (self.bits - 1))) >> self.bits;
130 let val = *el + pred;
131 *el = val;
132 self.buf[delay_pos] = val.min(32767).max(-32768);
133 if self.new {
134 let aval = val.abs();
135 let sign = val2sign(val);
136 self.buf[adapt_pos] = if aval == 0 {
137 0
138 } else if aval <= self.avg * 4 / 3 {
139 sign * 8
140 } else if aval <= self.avg * 3 {
141 sign * 16
142 } else {
143 sign * 32
144 };
145 self.avg += (aval - self.avg) / 16;
146 self.buf[adapt_pos - 1] >>= 1;
147 self.buf[adapt_pos - 2] >>= 1;
148 self.buf[adapt_pos - 8] >>= 1;
149 } else {
150 self.buf[adapt_pos] = 4 * val2sign(val);
151 self.buf[adapt_pos - 4] >>= 1;
152 self.buf[adapt_pos - 8] >>= 1;
153 }
154 delay_pos += 1;
155 adapt_pos += 1;
156 if delay_pos == HISTORY_SIZE + self.order * 2 {
157 delay_pos = self.order * 2;
158 adapt_pos = self.order;
159 for i in 0..self.order * 2 {
160 self.buf[i] = self.buf[HISTORY_SIZE + i];
161 }
162 }
163 }
164 }
165}
166
167#[derive(Clone,Copy,Default)]
168struct LastFilterContext {
169 last_a: i32,
170 filter_a: i32,
171 filter_b: i32,
172 coeffs_a: [i32; 4],
173 coeffs_b: [i32; 5],
174 delay_a: [i32; 4],
175 adapt_a: [i32; 4],
176 delay_b: [i32; 5],
177 adapt_b: [i32; 5],
178}
179
180impl LastFilterContext {
181 fn init(&mut self) {
182 const COEFFS_A_NEW: [i32; 4] = [360, 317, -109, 98];
183
184 self.filter_a = 0;
185 self.filter_b = 0;
186 self.coeffs_a = COEFFS_A_NEW;
187 self.coeffs_b = [0; 5];
188 self.last_a = 0;
189 self.delay_a = [0; 4];
190 self.adapt_a = [0; 4];
191 self.delay_b = [0; 5];
192 self.adapt_b = [0; 5];
193 }
194 fn predict_a(&mut self) -> i32 {
195 for i in (0..3).rev() {
196 self.delay_a[i + 1] = self.delay_a[i];
197 self.adapt_a[i + 1] = self.adapt_a[i];
198 }
199 self.delay_a[0] = self.last_a;
200 self.delay_a[1] = self.last_a - self.delay_a[1];
201 self.adapt_a[0] = val2sign(self.delay_a[0]);
202 self.adapt_a[1] = val2sign(self.delay_a[1]);
203
204 self.delay_a[0] * self.coeffs_a[0] +
205 self.delay_a[1] * self.coeffs_a[1] +
206 self.delay_a[2] * self.coeffs_a[2] +
207 self.delay_a[3] * self.coeffs_a[3]
208 }
209 fn predict_b(&mut self, other_a: i32) -> i32 {
210 for i in (0..4).rev() {
211 self.delay_b[i + 1] = self.delay_b[i];
212 self.adapt_b[i + 1] = self.adapt_b[i];
213 }
214 self.delay_b[0] = other_a - ((self.filter_b * 31) >> 5);
215 self.delay_b[1] = self.delay_b[0] - self.delay_b[1];
216 self.adapt_b[0] = val2sign(self.delay_b[0]);
217 self.adapt_b[1] = val2sign(self.delay_b[1]);
218
219 self.filter_b = other_a;
220
221 (self.delay_b[0] * self.coeffs_b[0] +
222 self.delay_b[1] * self.coeffs_b[1] +
223 self.delay_b[2] * self.coeffs_b[2] +
224 self.delay_b[3] * self.coeffs_b[3] +
225 self.delay_b[4] * self.coeffs_b[4]) >> 1
226 }
227 fn update_a(&mut self, pred: i32, diff: i32) -> i32 {
228 self.last_a = diff + (pred >> 10);
229 let sign = val2sign(diff);
230 for i in 0..4 {
231 self.coeffs_a[i] += self.adapt_a[i] * sign;
232 }
233 self.filter_a = self.last_a + ((self.filter_a * 31) >> 5);
234
235 self.filter_a
236 }
237 fn update_b(&mut self, diff: i32) {
238 let sign = val2sign(diff);
239 for i in 0..5 {
240 self.coeffs_b[i] += self.adapt_b[i] * sign;
241 }
242 }
243 fn predict_3930(&mut self, diff: i32) -> i32 {
244 for i in (0..3).rev() {
245 self.delay_a[i + 1] = self.delay_a[i];
246 }
247 self.delay_a[0] = self.last_a;
248 let d0 = self.delay_a[0];
249 let d1 = self.delay_a[0] - self.delay_a[1];
250 let d2 = self.delay_a[1] - self.delay_a[2];
251 let d3 = self.delay_a[2] - self.delay_a[3];
252
253 let pred = (self.coeffs_a[0] * d0 +
254 self.coeffs_a[1] * d1 +
255 self.coeffs_a[2] * d2 +
256 self.coeffs_a[3] * d3) >> 9;
257 self.last_a = diff + pred;
258 self.filter_a = self.last_a + ((self.filter_a * 31) >> 5);
259
260 let sign = val2sign(diff);
261 self.coeffs_a[0] += if d0 < 0 { sign } else { -sign };
262 self.coeffs_a[1] += if d1 < 0 { sign } else { -sign };
263 self.coeffs_a[2] += if d2 < 0 { sign } else { -sign };
264 self.coeffs_a[3] += if d3 < 0 { sign } else { -sign };
265
266 self.filter_a
267 }
268}
269
270impl NewFilt {
271 fn new(version: u16, compression: u16) -> Self {
272 let cidx = (compression / 1000) as usize - 1;
273 let mut obj = Self {
274 version,
275 filters: [NFilterContext::default(), NFilterContext::default(), NFilterContext::default()],
276 lfilt: LastFilterContext::default(),
277 rfilt: LastFilterContext::default(),
278 };
279 obj.version = version;
280 let new = version >= 3980;
281 for i in 0..3 {
282 let (ord16, bits) = NEW_FILTER_PARAMS[cidx][i];
283 obj.filters[i] = NFilterContext::new(ord16, bits, new);
284 }
285 obj
286 }
287 fn filter_mono(&mut self, dst: &mut [i32]) {
288 for filt in self.filters.iter_mut() {
289 filt.reset();
290 filt.apply(dst);
291 }
292 self.lfilt.init();
293 if self.version >= 3950 {
294 for el in dst.iter_mut() {
295 let pred = self.lfilt.predict_a();
296 *el = self.lfilt.update_a(pred, *el);
297 }
298 } else {
299 for el in dst.iter_mut() {
300 *el = self.lfilt.predict_3930(*el);
301 }
302 }
303 }
304 fn filter_stereo(&mut self, l: &mut [i32], r: &mut [i32]) {
305 for filt in self.filters.iter_mut() {
306 filt.reset();
307 filt.apply(l);
308 filt.reset();
309 filt.apply(r);
310 }
311 self.lfilt.init();
312 self.rfilt.init();
313 if self.version >= 3950 {
314 for (l, r) in l.iter_mut().zip(r.iter_mut()) {
315 let mut pred = self.lfilt.predict_a();
316 pred += self.lfilt.predict_b(self.rfilt.filter_a);
317 let new_l = self.lfilt.update_a(pred, *l);
318 self.lfilt.update_b(*l);
319 *l = new_l;
320
321 let mut pred = self.rfilt.predict_a();
322 pred += self.rfilt.predict_b(self.lfilt.filter_a);
323 let new_r = self.rfilt.update_a(pred, *r);
324 self.rfilt.update_b(*r);
325 *r = new_r;
326 }
327 } else {
328 for (l, r) in l.iter_mut().zip(r.iter_mut()) {
329 let new_l = self.lfilt.predict_3930(*r);
330 let new_r = self.rfilt.predict_3930(*l);
331 *l = new_l;
332 *r = new_r;
333 }
334 }
335 }
336}
337
338impl OldFilt {
339 fn new(version: u16, compression: u16) -> Self {
340 Self {
341 version, compression
342 }
343 }
344 fn filter(&mut self, dst: &mut [i32]) {
345 match self.compression {
346 1000 => {
347 Self::filter_fast(dst);
348 },
349 2000 => {
350 Self::filter_normal(dst, 4, 10);
351 },
352 3000 => {
353 Self::filter_high(dst, 16, 9);
354 Self::filter_normal(dst, 16, 10);
355 },
356 4000 => {
357 if self.version < 3830 {
358 Self::filter_high(dst, 128, 11);
359 Self::filter_normal(dst, 128, 10);
360 } else {
361 Self::filter_extra_high(dst);
362 Self::filter_high(dst, 256, 12);
363 Self::filter_normal(dst, 256, 11);
364 }
365 },
366 _ => unreachable!(),
367 };
368 }
369 fn filter_fast(dst: &mut [i32]) {
370 const COEFF_A_FAST: i32 = 375;
371
372 if dst.len() <= 3 {
373 return;
374 }
375 let mut delay = [dst[1], dst[0]];
376 let mut last = dst[2];
377 let mut filter = dst[2];
378 let mut weight = COEFF_A_FAST;
379 for el in dst[3..].iter_mut() {
380 delay[1] = delay[0];
381 delay[0] = last;
382 let pred = delay[0] * 2 - delay[1];
383 last = *el + ((pred * weight) >> 9);
384 if (*el ^ pred) > 0 {
385 weight += 1;
386 } else {
387 weight -= 1;
388 }
389 filter += last;
390 *el = filter;
391 }
392 }
393 fn filter_normal(dst: &mut [i32], start: usize, shift: u8) {
394 const COEFFS_A_NORMAL: [i32; 3] = [64, 115, 64];
395 const COEFFS_B_NORMAL: [i32; 2] = [740, 0];
396
397 let mut last = 0;
398 let mut coeffs_a = COEFFS_A_NORMAL;
399 let mut coeffs_b = COEFFS_B_NORMAL;
400 let mut filter_a = 0;
401 let mut filter_b = 0;
402 let mut delay_a = [0; 3];
403 let mut delay_b = [0; 2];
404
405 for (i, el) in dst.iter_mut().enumerate() {
406 delay_a[2] = delay_a[1]; delay_a[1] = delay_a[0]; delay_a[0] = last;
407 delay_b[1] = delay_b[0]; delay_b[0] = filter_b;
408 if i < start {
409 let val = *el + filter_a;
410 last = *el;
411 filter_b = *el;
412 filter_a = val;
413 *el = val;
414 continue;
415 }
416 let a0 = delay_a[0] + (delay_a[2] - delay_a[1]) * 8;
417 let a1 = (delay_a[0] - delay_a[1]) * 2;
418 let a2 = delay_a[0];
419 let b0 = delay_b[0] * 2 - delay_b[1];
420 let b1 = delay_b[0];
421
422 let pred_a = a0 * coeffs_a[0] + a1 * coeffs_a[1] + a2 * coeffs_a[2];
423 let pred_b = b0 * coeffs_b[0] - b1 * coeffs_b[1];
424
425 let sign = val2sign(*el);
426 coeffs_a[0] += (((a0 >> 30) & 2) - 1) * sign;
427 coeffs_a[1] += (((a1 >> 28) & 8) - 4) * sign;
428 coeffs_a[2] += (((a2 >> 28) & 8) - 4) * sign;
429 last = *el + (pred_a >> 11);
430
431 let sign = val2sign(last);
432 coeffs_b[0] += (((b0 >> 29) & 4) - 2) * sign;
433 coeffs_b[1] -= (((b1 >> 30) & 2) - 1) * sign;
434
435 filter_b = last + (pred_b >> shift);
436 filter_a = filter_b + ((filter_a * 31) >> 5);
437
438 *el = filter_a;
439 }
440 }
441 fn filter_high(dst: &mut [i32], order: usize, shift: u8) {
442 let mut coeffs = [0i32; 256];
443 let mut delay = [0i32; 256];
444 if dst.len() <= order {
445 return;
446 }
447 delay[..order].copy_from_slice(&dst[..order]);
448 for el in dst[order..].iter_mut() {
449 let sign = val2sign(*el);
450 let mut sum = 0;
451 for i in 0..order {
452 sum += delay[i] * coeffs[i];
453 coeffs[i] -= (((delay[i] >> 30) & 2) - 1) * sign;
454 }
455 *el -= sum >> shift;
456 for i in 0..order-1 {
457 delay[i] = delay[i + 1];
458 }
459 delay[order - 1] = *el;
460 }
461 }
462 fn filter_extra_high(dst: &mut [i32]) {
463 let mut coeffs = [0i32; 8];
464 let mut delay = [0i32; 8];
465 for el in dst[256..].iter_mut() {
466 let sign = val2sign(*el);
467 let mut sum = 0;
468 for i in 0..8 {
469 sum += delay[i] * coeffs[i];
470 coeffs[i] -= (((delay[i] >> 30) & 2) - 1) * sign;
471 }
472 for i in (0..7).rev() {
473 delay[i + 1] = delay[i];
474 }
475 delay[0] = *el;
476 *el -= sum >> 9;
477 }
478 }
479}