lc3_codec/decoder/
packet_loss_concealment.rs1use crate::common::{complex::Scaler, config::Lc3Config};
2
3use super::side_info::LongTermPostFilterInfo;
4
5pub struct PacketLossConcealment<'a> {
8 spec_lines_last_good: &'a mut [Scaler],
10
11 num_lost_frames: usize,
13
14 alpha: Scaler,
16
17 plc_seed: usize,
19
20 ne: usize,
22}
23
24impl<'a> PacketLossConcealment<'a> {
25 pub fn new(ne: usize, scaler_buf: &'a mut [Scaler]) -> (Self, &'a mut [Scaler]) {
26 let (spec_lines_last_good, scaler_buf) = scaler_buf.split_at_mut(ne);
27
28 (
29 Self {
30 spec_lines_last_good,
31 plc_seed: 24607,
32 num_lost_frames: 0,
33 alpha: 1.0,
34 ne,
35 },
36 scaler_buf,
37 )
38 }
39
40 pub const fn calc_working_buffer_length(config: &Lc3Config) -> usize {
41 config.ne
42 }
43
44 pub fn save(&mut self, spec_lines: &[Scaler]) {
51 self.num_lost_frames = 0;
52 self.alpha = 1.0;
53 self.spec_lines_last_good[..self.ne].copy_from_slice(&spec_lines[..self.ne]);
54 }
55
56 pub fn load_into(&mut self, spec_lines: &mut [Scaler]) -> LongTermPostFilterInfo {
64 if self.num_lost_frames >= 4 {
65 self.alpha *= if self.num_lost_frames < 8 { 0.9 } else { 0.85 };
66 }
67 self.num_lost_frames += 1;
68
69 for (current, last_good) in spec_lines.iter_mut().zip(self.spec_lines_last_good.iter()) {
70 self.plc_seed = (16831 + self.plc_seed * 12821) & 0xFFFF;
71
72 *current = if self.plc_seed < 0x8000 {
73 last_good * self.alpha
74 } else {
75 last_good * -self.alpha
76 };
77 }
78
79 LongTermPostFilterInfo {
81 is_active: false,
82 pitch_index: 0,
83 pitch_present: false,
84 }
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 extern crate std;
91 use super::*;
92
93 #[test]
94 fn save_and_load() {
95 let mut spec_lines = [-2268.137, 7869.9785, 15884.984, 9776.979];
96 let mut scaler_buf = [0.; 4];
97 let (mut packet_loss, _) = PacketLossConcealment::new(spec_lines.len(), &mut scaler_buf);
98
99 packet_loss.save(&spec_lines);
100 packet_loss.load_into(&mut spec_lines);
101 packet_loss.load_into(&mut spec_lines);
102 packet_loss.load_into(&mut spec_lines);
103
104 let spec_lines_expected = [2268.137, 7869.9785, -15884.984, -9776.979];
105 assert_eq!(spec_lines, spec_lines_expected);
106 }
107}