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
//! Deep packet loss concealment (deep PLC) of libopus 1.6.1, compiled with
//! the `deep-plc` feature.
//!
//! When a packet is lost, the decoder of libopus 1.5 and later can make up
//! the missing speech with three neural networks, at decoder complexity 5
//! and above:
//!
//! - PitchDNN estimates the pitch of each 10 ms of past audio
//! (`pitchdnn`, libopus `dnn/pitchdnn.c`);
//! - the feature analysis describes each 10 ms of past audio with 20 values
//! (`features`, libopus `dnn/lpcnet_enc.c`);
//! - the PLC network predicts the 20 values of the lost frames from the
//! past ones (`compute_plc_pred` in `lpcnet_plc`);
//! - FARGAN, a vocoder, turns those values into 16 kHz audio (`fargan`,
//! libopus `dnn/fargan.c`).
//!
//! `DeepPlc` (`lpcnet_plc`, libopus `dnn/lpcnet_plc.c`) holds the state of
//! all of them for one decoder: 150 ms of past audio at 16 kHz, the
//! positions of the analysis, the recurrent states and the queue of
//! features that the deep redundancy (DRED) decoder would fill. It works in
//! frames of 10 ms at 16 kHz (`LPCNET_FRAME_SIZE`, 160 samples):
//!
//! - `DeepPlc::update` appends a frame that was decoded;
//! - `DeepPlc::conceal` makes up a lost frame and appends it;
//! - `DeepPlc::update_from_celt` appends the last 40 ms of a CELT decoder's
//! history, resampled from 48 kHz to 16 kHz (libopus `update_plc_state`).
//!
//! The weights are not part of the state: `conceal` takes the models
//! (`DeepPlcModels`, from `DecoderDnn::deep_plc`) and the kernel variant
//! (`DnnArch`) as arguments.
//!
//! # Rounding
//!
//! Every function gives the bits of libopus 1.6.1 built for 64-bit ARM
//! without loop vectorization (`-O2 -fno-vectorize -fno-slp-vectorize`), on
//! every target. The rules are those of `freq.rs`: a C expression
//! `a * b + c` that clang contracts is one fused multiply-add; a `double`
//! constant or a `double` math function makes the expression `double`;
//! sums keep the order of the C loops. Each place was checked in the
//! assembly of that build.
//!
//! The math library functions (`exp`, `exp2`, `log`, `sqrt`, `floor`) are
//! those of the platform with `std`, as in libopus, and those of the `libm`
//! crate without `std`. Each result is rounded to `f32` or to an integer
//! right after, so a last-bit difference between libraries shows only in
//! rare cases.
pub use FarganState;
pub use LpcnetEncState;
pub use ;
pub use PitchDnnState;
/// `NB_FEATURES` (`dnn/lpcnet.h:32`): the features of one 10 ms frame that
/// the PLC network predicts and FARGAN reads: 18 cepstral values, the pitch
/// and the pitch correlation.
pub const NB_FEATURES: usize = 20;
/// `NB_TOTAL_FEATURES` (`dnn/lpcnet.h:33`): `NB_FEATURES` followed by the
/// 16 LPC coefficients.
pub const NB_TOTAL_FEATURES: usize = 36;
/// `LPCNET_FRAME_SIZE` (`dnn/lpcnet.h:36`): 10 ms at 16 kHz, the unit of
/// `DeepPlc::update` and `DeepPlc::conceal`.
pub const LPCNET_FRAME_SIZE: usize = 160;
/// `PITCH_MIN_PERIOD` (`dnn/pitchdnn.h:10`).
pub const PITCH_MIN_PERIOD: usize = 32;
/// `PITCH_MAX_PERIOD` (`dnn/pitchdnn.h:11`).
pub const PITCH_MAX_PERIOD: usize = 256;
/// `NB_XCORR_FEATURES` (`dnn/pitchdnn.h:14`): the cross-correlation inputs
/// of PitchDNN, one per lag from 32 to 255.
pub const NB_XCORR_FEATURES: usize = PITCH_MAX_PERIOD - PITCH_MIN_PERIOD;
/// `PITCH_IF_MAX_FREQ` (`dnn/lpcnet_private.h:18`): the bins of the
/// instantaneous frequency inputs of PitchDNN.
pub const PITCH_IF_MAX_FREQ: usize = 30;
/// `PITCH_IF_FEATURES` (`dnn/lpcnet_private.h:19`): the instantaneous
/// frequency inputs of PitchDNN.
pub const PITCH_IF_FEATURES: usize = 3 * PITCH_IF_MAX_FREQ - 2;
/// `CONT_VECTORS` (`dnn/lpcnet_private.h:21`): the feature vectors that
/// FARGAN reads when it starts on past audio.
pub const CONT_VECTORS: usize = 5;
/// `PLC_MAX_FEC` (`dnn/lpcnet_private.h:15`): the room of the queue of
/// features that the DRED decoder fills.
pub const PLC_MAX_FEC: usize = 104;
/// `PLC_BUF_SIZE` (`dnn/lpcnet_private.h:49`): the past audio that
/// `DeepPlc` keeps, 150 ms at 16 kHz.
pub const PLC_BUF_SIZE: usize = * LPCNET_FRAME_SIZE;
/// The input of the PLC network (`2*NB_BANDS+NB_FEATURES+1` in
/// `dnn/lpcnet_plc.c`): 36 Burg cepstral values, 20 features and a flag
/// (1 for analysed audio, -1 for DRED features, 0 for a pure prediction).
pub const PLC_INPUT_SIZE: usize = 2 * crateNB_BANDS + NB_FEATURES + 1;
/// `MIN16` and `MIN32` of the float build: `a < b ? a : b`, in this
/// argument order (it decides the result when one value is NaN).
pub
/// `MAX16` and `MAX32` of the float build: `a > b ? a : b`, in this
/// argument order.
pub
/// `(int)floor(.5+256./pow(2.f,((1./60.)*((f+1.5)*60))))`: the pitch
/// period in samples of the pitch feature `f` (`dnn/lpcnet_enc.c:188`,
/// `dnn/fargan.c:154`, `:205`). All in `double`; clang turns `pow(2, x)`
/// into `exp2(x)`. A NaN gives 0 and values out of range saturate, as the
/// `fcvtms` instruction does.
pub