1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
use crate::silk::cng::silk_cng_reset;
use crate::silk::decoder_structs::SilkDecoderState;
use crate::silk::define::*;
use crate::silk::plc::silk_plc_reset;
use crate::silk::resampler::SilkResampler;
use crate::silk::tables_nlsf::*;
/// Set the sampling rate of one channel (libopus `silk_decoder_set_fs`).
///
/// `fs_khz` is the SILK rate of the packet, `fs_api_hz` the output rate.
/// Returns 0, or a negative value when a rate is not supported.
pub fn silk_decoder_set_fs(dec: &mut SilkDecoderState, fs_khz: i32, fs_api_hz: i32) -> i32 {
if fs_khz != 8 && fs_khz != 12 && fs_khz != 16 {
return -1;
}
let mut ret = 0;
// libopus decoder_set_fs.c: the caller sets `nb_subfr` first (4 for a
// 20 ms SILK frame, 2 for a 10 ms one) and the frame length and the
// pitch contour table below follow from it, so a 10 ms frame gets the
// 10 ms table. A state whose `nb_subfr` was never set counts as 20 ms.
if dec.nb_subfr != (MAX_NB_SUBFR / 2) as i32 {
dec.nb_subfr = MAX_NB_SUBFR as i32;
}
dec.subfr_length = (SUB_FRAME_LENGTH_MS as i32) * fs_khz;
let frame_length = dec.subfr_length * dec.nb_subfr;
// The resampler starts afresh when either of its two rates changes.
// libopus compares with `fs_API_hz`; see `resampler_api_hz` for why
// this compares with the rate the resampler really has.
if dec.fs_khz != fs_khz || dec.resampler_api_hz != fs_api_hz {
let err = dec.resampler_state.init(fs_khz * 1000, fs_api_hz);
dec.resampler_api_hz = if err == 0 { fs_api_hz } else { 0 };
ret += err;
}
dec.fs_api_hz = fs_api_hz;
if dec.fs_khz != fs_khz || frame_length != dec.frame_length {
dec.pitch_contour_icdf = if fs_khz == 8 {
if dec.nb_subfr == MAX_NB_SUBFR as i32 {
&crate::silk::tables::SILK_PITCH_CONTOUR_NB_ICDF
} else {
&crate::silk::tables::SILK_PITCH_CONTOUR_10_MS_NB_ICDF
}
} else if dec.nb_subfr == MAX_NB_SUBFR as i32 {
&crate::silk::tables::SILK_PITCH_CONTOUR_ICDF
} else {
&crate::silk::tables::SILK_PITCH_CONTOUR_10_MS_ICDF
};
if dec.fs_khz != fs_khz {
// Bandwidth switch (libopus decoder_set_fs.c): reset the state that
// is tied to the old rate. A `lag_prev` from the old rate (e.g.
// 288 at 16 kHz) would index out of bounds in silk_decode_core
// at 8 kHz.
dec.ltp_mem_length = (LTP_MEM_LENGTH_MS as i32) * fs_khz;
// NB and MB share the order-10 NLSF codebook; only WB codes 16
// coefficients. Set both from one branch, as libopus does: the
// decoder reads `ps_nlsf_cb.order` NLSF indices and filters with
// `lpc_order` coefficients, so the two must match.
let (lpc_order, nlsf_cb) = if fs_khz == 8 || fs_khz == 12 {
(MIN_LPC_ORDER, &SILK_NLSF_CB_NB_MB)
} else {
(MAX_LPC_ORDER, &SILK_NLSF_CB_WB)
};
dec.lpc_order = lpc_order as i32;
dec.ps_nlsf_cb = Some(nlsf_cb);
dec.pitch_lag_low_bits_icdf = match fs_khz {
8 => &crate::silk::tables::SILK_UNIFORM4_ICDF,
12 => &crate::silk::tables::SILK_UNIFORM6_ICDF,
_ => &crate::silk::tables::SILK_UNIFORM8_ICDF,
};
dec.first_frame_after_reset = 1;
dec.lag_prev = 100;
dec.last_gain_index = 10;
dec.prev_signal_type = TYPE_NO_VOICE_ACTIVITY;
dec.out_buf.fill(0);
dec.s_lpc_q14_buf.fill(0);
}
dec.fs_khz = fs_khz;
dec.frame_length = frame_length;
}
ret
}
/// Put one channel back into its start state (libopus `silk_reset_decoder`).
///
/// libopus clears the whole state, the sampling rate included. The next
/// `silk_decoder_set_fs` therefore sets up everything that depends on the
/// rate again: the tables, the filter memories and the resampler.
///
/// Three kinds of fields get a usable value instead of the zero that
/// libopus writes, so that no call order can index out of range:
/// `lag_prev` and `last_gain_index` (to the values `silk_decoder_set_fs`
/// gives them anyway) and the table references.
pub fn silk_reset_decoder(ps_dec: &mut SilkDecoderState) -> i32 {
ps_dec.prev_gain_q16 = 1 << 16;
ps_dec.exc_q14.fill(0);
ps_dec.s_lpc_q14_buf.fill(0);
ps_dec.out_buf.fill(0);
ps_dec.lag_prev = 100;
ps_dec.last_gain_index = 10;
ps_dec.fs_khz = 0;
ps_dec.fs_api_hz = 0;
ps_dec.nb_subfr = 0;
ps_dec.frame_length = 0;
ps_dec.subfr_length = 0;
ps_dec.ltp_mem_length = 0;
ps_dec.lpc_order = 0;
ps_dec.prev_nlsf_q15.fill(0);
ps_dec.first_frame_after_reset = 1;
ps_dec.pitch_lag_low_bits_icdf = &crate::silk::tables::SILK_UNIFORM4_ICDF;
ps_dec.pitch_contour_icdf = &crate::silk::tables::SILK_PITCH_CONTOUR_ICDF;
ps_dec.n_frames_decoded = 0;
ps_dec.n_frames_per_packet = 0;
ps_dec.ec_prev_signal_type = 0;
ps_dec.ec_prev_lag_index = 0;
ps_dec.vad_flags.fill(0);
ps_dec.lbrr_flag = 0;
ps_dec.lbrr_flags.fill(0);
ps_dec.resampler_state = SilkResampler::default();
ps_dec.resampler_api_hz = 0;
ps_dec.ps_nlsf_cb = Some(&SILK_NLSF_CB_WB);
ps_dec.indices = Default::default();
ps_dec.loss_cnt = 0;
ps_dec.prev_signal_type = TYPE_NO_VOICE_ACTIVITY;
// Comfort noise state (libopus clears it, then calls silk_CNG_Reset).
let cng = &mut ps_dec.s_cng;
cng.cng_exc_buf_q14.fill(0);
cng.cng_smth_nlsf_q15.fill(0);
cng.cng_synth_state.fill(0);
cng.fs_khz = 0;
silk_cng_reset(ps_dec);
// Concealment state (libopus clears it, then calls silk_PLC_Reset).
let plc = &mut ps_dec.s_plc;
plc.ltp_coef_q14.fill(0);
plc.prev_lpc_q12.fill(0);
plc.last_frame_lost = 0;
plc.rand_seed = 0;
plc.rand_scale_q14 = 0;
plc.conc_energy = 0;
plc.conc_energy_shift = 0;
plc.prev_ltp_scale_q14 = 0;
plc.fs_khz = 0;
plc.enable_deep_plc = 0;
silk_plc_reset(ps_dec);
// libopus init_decoder.c:61-64: OSCE goes back to its default method.
// The bandwidth extension state lies before the part libopus clears,
// so it stays.
#[cfg(feature = "osce")]
crate::dnn::osce::osce_reset(&mut ps_dec.osce, crate::dnn::osce::OSCE_DEFAULT_METHOD);
0
}
/// Initialise one channel (libopus `silk_init_decoder`). In libopus this
/// clears the state and then calls `silk_reset_decoder`, which clears it
/// too, so the two do the same, except for the bandwidth extension state:
/// only `silk_init_decoder` clears it (to zero, not to the state of
/// `osce_bwe_reset`). libopus runs it when a decoder is created and for
/// the second channel when the stream changes from mono to stereo.
pub fn silk_init_decoder(ps_dec: &mut SilkDecoderState) -> i32 {
#[cfg(feature = "osce-bwe")]
clear_bwe(&mut ps_dec.osce_bwe);
silk_reset_decoder(ps_dec)
}
/// Sets a bandwidth extension state to zero, as `silk_init_decoder`
/// leaves it.
#[cfg(feature = "osce-bwe")]
fn clear_bwe(state: &mut crate::dnn::osce::OsceBweChannel) {
*state = crate::dnn::osce::OsceBweChannel::new();
}
pub fn silk_create_decoder() -> SilkDecoderState {
let mut dec = SilkDecoderState::default();
silk_init_decoder(&mut dec);
dec
}