1*a58d3d2aSXin Li /* Copyright (c) 2023 Amazon */
2*a58d3d2aSXin Li /*
3*a58d3d2aSXin Li Redistribution and use in source and binary forms, with or without
4*a58d3d2aSXin Li modification, are permitted provided that the following conditions
5*a58d3d2aSXin Li are met:
6*a58d3d2aSXin Li
7*a58d3d2aSXin Li - Redistributions of source code must retain the above copyright
8*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer.
9*a58d3d2aSXin Li
10*a58d3d2aSXin Li - Redistributions in binary form must reproduce the above copyright
11*a58d3d2aSXin Li notice, this list of conditions and the following disclaimer in the
12*a58d3d2aSXin Li documentation and/or other materials provided with the distribution.
13*a58d3d2aSXin Li
14*a58d3d2aSXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15*a58d3d2aSXin Li ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16*a58d3d2aSXin Li LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17*a58d3d2aSXin Li A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
18*a58d3d2aSXin Li OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*a58d3d2aSXin Li EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*a58d3d2aSXin Li PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21*a58d3d2aSXin Li PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22*a58d3d2aSXin Li LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23*a58d3d2aSXin Li NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24*a58d3d2aSXin Li SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*a58d3d2aSXin Li */
26*a58d3d2aSXin Li
27*a58d3d2aSXin Li #ifdef HAVE_CONFIG_H
28*a58d3d2aSXin Li #include "config.h"
29*a58d3d2aSXin Li #endif
30*a58d3d2aSXin Li
31*a58d3d2aSXin Li #include "fwgan.h"
32*a58d3d2aSXin Li #include "os_support.h"
33*a58d3d2aSXin Li #include "freq.h"
34*a58d3d2aSXin Li #include "fwgan_data.h"
35*a58d3d2aSXin Li #include "lpcnet.h"
36*a58d3d2aSXin Li #include "pitch.h"
37*a58d3d2aSXin Li #include "nnet.h"
38*a58d3d2aSXin Li #include "lpcnet_private.h"
39*a58d3d2aSXin Li
40*a58d3d2aSXin Li #define FEAT_IN_SIZE (BFCC_WITH_CORR_UPSAMPLER_FC_OUT_SIZE/4 + FWGAN_FRAME_SIZE/2)
41*a58d3d2aSXin Li
42*a58d3d2aSXin Li #define FWGAN_FEATURES (NB_FEATURES-1)
43*a58d3d2aSXin Li
pitch_embeddings(float * pembed,float * phase,double w0)44*a58d3d2aSXin Li static void pitch_embeddings(float *pembed, float *phase, double w0) {
45*a58d3d2aSXin Li int i;
46*a58d3d2aSXin Li float wreal, wimag;
47*a58d3d2aSXin Li #if 1
48*a58d3d2aSXin Li /* This Taylor expansion should be good enough since w0 is always small. */
49*a58d3d2aSXin Li float w2 = w0*w0;
50*a58d3d2aSXin Li wreal = 1 - .5*w2*(1.f - 0.083333333f*w2);
51*a58d3d2aSXin Li wimag = w0*(1 - 0.166666667f*w2*(1.f - 0.05f*w2));
52*a58d3d2aSXin Li #else
53*a58d3d2aSXin Li wreal = cos(w0);
54*a58d3d2aSXin Li wimag = sin(w0);
55*a58d3d2aSXin Li #endif
56*a58d3d2aSXin Li /* Speed-up phase reference by making phase a unit-norm complex value and rotating it
57*a58d3d2aSXin Li by exp(-i*w0) each sample. */
58*a58d3d2aSXin Li for (i=0;i<SUBFRAME_SIZE;i++) {
59*a58d3d2aSXin Li float tmp;
60*a58d3d2aSXin Li tmp = phase[0]*wreal - phase[1]*wimag;
61*a58d3d2aSXin Li phase[1] = phase[0]*wimag + phase[1]*wreal;
62*a58d3d2aSXin Li phase[0] = tmp;
63*a58d3d2aSXin Li pembed[i] = phase[1];
64*a58d3d2aSXin Li pembed[SUBFRAME_SIZE+i] = phase[0];
65*a58d3d2aSXin Li }
66*a58d3d2aSXin Li /* Renormalize once per sub-frame, though we could probably do it even less frequently. */
67*a58d3d2aSXin Li {
68*a58d3d2aSXin Li float r = 1.f/sqrt(phase[0]*phase[0] + phase[1]*phase[1]);
69*a58d3d2aSXin Li phase[0] *= r;
70*a58d3d2aSXin Li phase[1] *= r;
71*a58d3d2aSXin Li }
72*a58d3d2aSXin Li }
73*a58d3d2aSXin Li
compute_wlpc(float lpc[LPC_ORDER],const float * features)74*a58d3d2aSXin Li static void compute_wlpc(float lpc[LPC_ORDER], const float *features) {
75*a58d3d2aSXin Li float lpc_weight;
76*a58d3d2aSXin Li int i;
77*a58d3d2aSXin Li lpc_from_cepstrum(lpc, features);
78*a58d3d2aSXin Li lpc_weight = 1.f;
79*a58d3d2aSXin Li for (i=0;i<LPC_ORDER;i++) {
80*a58d3d2aSXin Li lpc_weight *= FWGAN_GAMMA;
81*a58d3d2aSXin Li lpc[i] *= lpc_weight;
82*a58d3d2aSXin Li }
83*a58d3d2aSXin Li }
84*a58d3d2aSXin Li
run_fwgan_upsampler(FWGANState * st,float * cond,const float * features)85*a58d3d2aSXin Li static void run_fwgan_upsampler(FWGANState *st, float *cond, const float *features)
86*a58d3d2aSXin Li {
87*a58d3d2aSXin Li FWGAN *model;
88*a58d3d2aSXin Li model = &st->model;
89*a58d3d2aSXin Li celt_assert(FWGAN_FEATURES == model->bfcc_with_corr_upsampler_fc.nb_inputs);
90*a58d3d2aSXin Li celt_assert(BFCC_WITH_CORR_UPSAMPLER_FC_OUT_SIZE == model->bfcc_with_corr_upsampler_fc.nb_outputs);
91*a58d3d2aSXin Li compute_generic_dense(&model->bfcc_with_corr_upsampler_fc, cond, features, ACTIVATION_TANH);
92*a58d3d2aSXin Li }
93*a58d3d2aSXin Li
94*a58d3d2aSXin Li static void fwgan_synthesize_impl(FWGANState *st, float *pcm, const float *lpc, const float *features);
fwgan_cont(FWGANState * st,const float * pcm0,const float * features0)95*a58d3d2aSXin Li void fwgan_cont(FWGANState *st, const float *pcm0, const float *features0)
96*a58d3d2aSXin Li {
97*a58d3d2aSXin Li int i;
98*a58d3d2aSXin Li float norm2, norm_1;
99*a58d3d2aSXin Li float wpcm0[CONT_PCM_INPUTS];
100*a58d3d2aSXin Li float cont_inputs[CONT_PCM_INPUTS+1];
101*a58d3d2aSXin Li float tmp1[MAX_CONT_SIZE];
102*a58d3d2aSXin Li float tmp2[MAX_CONT_SIZE];
103*a58d3d2aSXin Li float lpc[LPC_ORDER];
104*a58d3d2aSXin Li float new_pcm[FWGAN_FRAME_SIZE];
105*a58d3d2aSXin Li FWGAN *model;
106*a58d3d2aSXin Li st->embed_phase[0] = 1;
107*a58d3d2aSXin Li model = &st->model;
108*a58d3d2aSXin Li compute_wlpc(lpc, features0);
109*a58d3d2aSXin Li /* Deemphasis memory is just the last continuation sample. */
110*a58d3d2aSXin Li st->deemph_mem = pcm0[CONT_PCM_INPUTS-1];
111*a58d3d2aSXin Li
112*a58d3d2aSXin Li /* Apply analysis filter, considering that the preemphasis and deemphasis filter
113*a58d3d2aSXin Li cancel each other in this case since the LPC filter is constant across that boundary.
114*a58d3d2aSXin Li */
115*a58d3d2aSXin Li for (i=LPC_ORDER;i<CONT_PCM_INPUTS;i++) {
116*a58d3d2aSXin Li int j;
117*a58d3d2aSXin Li wpcm0[i] = pcm0[i];
118*a58d3d2aSXin Li for (j=0;j<LPC_ORDER;j++) wpcm0[i] += lpc[j]*pcm0[i-j-1];
119*a58d3d2aSXin Li }
120*a58d3d2aSXin Li /* FIXME: Make this less stupid. */
121*a58d3d2aSXin Li for (i=0;i<LPC_ORDER;i++) wpcm0[i] = wpcm0[LPC_ORDER];
122*a58d3d2aSXin Li
123*a58d3d2aSXin Li /* The memory of the pre-empahsis is the last sample of the weighted signal
124*a58d3d2aSXin Li (ignoring preemphasis+deemphasis combination). */
125*a58d3d2aSXin Li st->preemph_mem = wpcm0[CONT_PCM_INPUTS-1];
126*a58d3d2aSXin Li /* The memory of the synthesis filter is the pre-emphasized continuation. */
127*a58d3d2aSXin Li for (i=0;i<LPC_ORDER;i++) st->syn_mem[i] = pcm0[CONT_PCM_INPUTS-1-i] - FWGAN_DEEMPHASIS*pcm0[CONT_PCM_INPUTS-2-i];
128*a58d3d2aSXin Li
129*a58d3d2aSXin Li norm2 = celt_inner_prod(wpcm0, wpcm0, CONT_PCM_INPUTS, st->arch);
130*a58d3d2aSXin Li norm_1 = 1.f/sqrt(1e-8f + norm2);
131*a58d3d2aSXin Li for (i=0;i<CONT_PCM_INPUTS;i++) cont_inputs[i+1] = norm_1*wpcm0[i];
132*a58d3d2aSXin Li cont_inputs[0] = log(sqrt(norm2) + 1e-7f);
133*a58d3d2aSXin Li
134*a58d3d2aSXin Li /* Continuation network */
135*a58d3d2aSXin Li compute_generic_dense(&model->cont_net_0, tmp1, cont_inputs, ACTIVATION_TANH);
136*a58d3d2aSXin Li compute_generic_dense(&model->cont_net_2, tmp2, tmp1, ACTIVATION_TANH);
137*a58d3d2aSXin Li compute_generic_dense(&model->cont_net_4, tmp1, tmp2, ACTIVATION_TANH);
138*a58d3d2aSXin Li compute_generic_dense(&model->cont_net_6, tmp2, tmp1, ACTIVATION_TANH);
139*a58d3d2aSXin Li compute_generic_dense(&model->cont_net_8, tmp1, tmp2, ACTIVATION_TANH);
140*a58d3d2aSXin Li celt_assert(CONT_NET_10_OUT_SIZE == model->cont_net_10.nb_outputs);
141*a58d3d2aSXin Li compute_generic_dense(&model->cont_net_10, st->cont, tmp1, ACTIVATION_TANH);
142*a58d3d2aSXin Li
143*a58d3d2aSXin Li /* Computing continuation for each layer. */
144*a58d3d2aSXin Li celt_assert(RNN_GRU_STATE_SIZE == model->rnn_cont_fc_0.nb_outputs);
145*a58d3d2aSXin Li compute_generic_dense(&model->rnn_cont_fc_0, st->rnn_state, st->cont, ACTIVATION_TANH);
146*a58d3d2aSXin Li
147*a58d3d2aSXin Li celt_assert(FWC1_STATE_SIZE == model->fwc1_cont_fc_0.nb_outputs);
148*a58d3d2aSXin Li compute_generic_dense(&model->fwc1_cont_fc_0, st->fwc1_state, st->cont, ACTIVATION_TANH);
149*a58d3d2aSXin Li celt_assert(FWC2_STATE_SIZE == model->fwc2_cont_fc_0.nb_outputs);
150*a58d3d2aSXin Li compute_generic_dense(&model->fwc2_cont_fc_0, st->fwc2_state, st->cont, ACTIVATION_TANH);
151*a58d3d2aSXin Li celt_assert(FWC3_STATE_SIZE == model->fwc3_cont_fc_0.nb_outputs);
152*a58d3d2aSXin Li compute_generic_dense(&model->fwc3_cont_fc_0, st->fwc3_state, st->cont, ACTIVATION_TANH);
153*a58d3d2aSXin Li celt_assert(FWC4_STATE_SIZE == model->fwc4_cont_fc_0.nb_outputs);
154*a58d3d2aSXin Li compute_generic_dense(&model->fwc4_cont_fc_0, st->fwc4_state, st->cont, ACTIVATION_TANH);
155*a58d3d2aSXin Li celt_assert(FWC5_STATE_SIZE == model->fwc5_cont_fc_0.nb_outputs);
156*a58d3d2aSXin Li compute_generic_dense(&model->fwc5_cont_fc_0, st->fwc5_state, st->cont, ACTIVATION_TANH);
157*a58d3d2aSXin Li celt_assert(FWC6_STATE_SIZE == model->fwc6_cont_fc_0.nb_outputs);
158*a58d3d2aSXin Li compute_generic_dense(&model->fwc6_cont_fc_0, st->fwc6_state, st->cont, ACTIVATION_TANH);
159*a58d3d2aSXin Li celt_assert(FWC7_STATE_SIZE == model->fwc7_cont_fc_0.nb_outputs);
160*a58d3d2aSXin Li compute_generic_dense(&model->fwc7_cont_fc_0, st->fwc7_state, st->cont, ACTIVATION_TANH);
161*a58d3d2aSXin Li
162*a58d3d2aSXin Li st->cont_initialized = 1;
163*a58d3d2aSXin Li /* Process the first frame, discard the first subframe, and keep the rest for the first
164*a58d3d2aSXin Li synthesis call. */
165*a58d3d2aSXin Li fwgan_synthesize_impl(st, new_pcm, lpc, features0);
166*a58d3d2aSXin Li OPUS_COPY(st->pcm_buf, &new_pcm[SUBFRAME_SIZE], FWGAN_FRAME_SIZE-SUBFRAME_SIZE);
167*a58d3d2aSXin Li }
168*a58d3d2aSXin Li
apply_gain(float * pcm,float c0,float * last_gain)169*a58d3d2aSXin Li static void apply_gain(float *pcm, float c0, float *last_gain) {
170*a58d3d2aSXin Li int i;
171*a58d3d2aSXin Li float gain = pow(10.f, (0.5f*c0/sqrt(18.f)));
172*a58d3d2aSXin Li for (i=0;i<SUBFRAME_SIZE;i++) pcm[i] *= *last_gain;
173*a58d3d2aSXin Li *last_gain = gain;
174*a58d3d2aSXin Li }
175*a58d3d2aSXin Li
fwgan_lpc_syn(float * pcm,float * mem,const float * lpc,float last_lpc[LPC_ORDER])176*a58d3d2aSXin Li static void fwgan_lpc_syn(float *pcm, float *mem, const float *lpc, float last_lpc[LPC_ORDER]) {
177*a58d3d2aSXin Li int i;
178*a58d3d2aSXin Li for (i=0;i<SUBFRAME_SIZE;i++) {
179*a58d3d2aSXin Li int j;
180*a58d3d2aSXin Li for (j=0;j<LPC_ORDER;j++) pcm[i] -= mem[j]*last_lpc[j];
181*a58d3d2aSXin Li OPUS_MOVE(&mem[1], &mem[0], LPC_ORDER-1);
182*a58d3d2aSXin Li mem[0] = pcm[i];
183*a58d3d2aSXin Li }
184*a58d3d2aSXin Li OPUS_COPY(last_lpc, lpc, LPC_ORDER);
185*a58d3d2aSXin Li }
186*a58d3d2aSXin Li
fwgan_preemphasis(float * pcm,float * preemph_mem)187*a58d3d2aSXin Li static void fwgan_preemphasis(float *pcm, float *preemph_mem) {
188*a58d3d2aSXin Li int i;
189*a58d3d2aSXin Li for (i=0;i<SUBFRAME_SIZE;i++) {
190*a58d3d2aSXin Li float tmp = pcm[i];
191*a58d3d2aSXin Li pcm[i] -= FWGAN_DEEMPHASIS * *preemph_mem;
192*a58d3d2aSXin Li *preemph_mem = tmp;
193*a58d3d2aSXin Li }
194*a58d3d2aSXin Li }
195*a58d3d2aSXin Li
fwgan_deemphasis(float * pcm,float * deemph_mem)196*a58d3d2aSXin Li static void fwgan_deemphasis(float *pcm, float *deemph_mem) {
197*a58d3d2aSXin Li int i;
198*a58d3d2aSXin Li for (i=0;i<SUBFRAME_SIZE;i++) {
199*a58d3d2aSXin Li pcm[i] += FWGAN_DEEMPHASIS * *deemph_mem;
200*a58d3d2aSXin Li *deemph_mem = pcm[i];
201*a58d3d2aSXin Li }
202*a58d3d2aSXin Li }
203*a58d3d2aSXin Li
run_fwgan_subframe(FWGANState * st,float * pcm,const float * cond,double w0,const float * lpc,float c0)204*a58d3d2aSXin Li static void run_fwgan_subframe(FWGANState *st, float *pcm, const float *cond, double w0, const float *lpc, float c0)
205*a58d3d2aSXin Li {
206*a58d3d2aSXin Li float tmp1[FWC1_FC_0_OUT_SIZE];
207*a58d3d2aSXin Li float tmp2[IMAX(RNN_GRU_STATE_SIZE, FWC2_FC_0_OUT_SIZE)];
208*a58d3d2aSXin Li float feat_in[FEAT_IN_SIZE];
209*a58d3d2aSXin Li float rnn_in[FEAT_IN_CONV1_CONV_OUT_SIZE];
210*a58d3d2aSXin Li float pembed[FWGAN_FRAME_SIZE/2];
211*a58d3d2aSXin Li FWGAN *model;
212*a58d3d2aSXin Li model = &st->model;
213*a58d3d2aSXin Li
214*a58d3d2aSXin Li pitch_embeddings(pembed, st->embed_phase, w0);
215*a58d3d2aSXin Li /* Interleave bfcc_cond and pembed for each subframe in feat_in. */
216*a58d3d2aSXin Li OPUS_COPY(&feat_in[BFCC_WITH_CORR_UPSAMPLER_FC_OUT_SIZE/4], &cond[0], BFCC_WITH_CORR_UPSAMPLER_FC_OUT_SIZE/4);
217*a58d3d2aSXin Li OPUS_COPY(&feat_in[0], &pembed[0], FWGAN_FRAME_SIZE/2);
218*a58d3d2aSXin Li
219*a58d3d2aSXin Li compute_generic_conv1d(&model->feat_in_conv1_conv, rnn_in, st->cont_conv1_mem, feat_in, FEAT_IN_CONV1_CONV_IN_SIZE, ACTIVATION_LINEAR);
220*a58d3d2aSXin Li celt_assert(FEAT_IN_NL1_GATE_OUT_SIZE == model->feat_in_nl1_gate.nb_outputs);
221*a58d3d2aSXin Li compute_gated_activation(&model->feat_in_nl1_gate, rnn_in, rnn_in, ACTIVATION_TANH);
222*a58d3d2aSXin Li
223*a58d3d2aSXin Li if (st->cont_initialized == 1) {
224*a58d3d2aSXin Li /* On the very first subframe we stop here. We only want to run the feat_in layer since the
225*a58d3d2aSXin Li others are initialized via the continuation network. */
226*a58d3d2aSXin Li OPUS_CLEAR(pcm, SUBFRAME_SIZE);
227*a58d3d2aSXin Li st->cont_initialized = 2;
228*a58d3d2aSXin Li apply_gain(pcm, c0, &st->last_gain);
229*a58d3d2aSXin Li OPUS_COPY(st->last_lpc, lpc, LPC_ORDER);
230*a58d3d2aSXin Li return;
231*a58d3d2aSXin Li }
232*a58d3d2aSXin Li
233*a58d3d2aSXin Li compute_generic_gru(&model->rnn_gru_input, &model->rnn_gru_recurrent, st->rnn_state, rnn_in);
234*a58d3d2aSXin Li celt_assert(IMAX(RNN_GRU_STATE_SIZE, FWC2_FC_0_OUT_SIZE) >= model->rnn_nl_gate.nb_outputs);
235*a58d3d2aSXin Li compute_gated_activation(&model->rnn_nl_gate, tmp2, st->rnn_state, ACTIVATION_TANH);
236*a58d3d2aSXin Li
237*a58d3d2aSXin Li compute_generic_conv1d(&model->fwc1_fc_0, tmp1, st->fwc1_state, tmp2, RNN_GRU_STATE_SIZE, ACTIVATION_LINEAR);
238*a58d3d2aSXin Li compute_gated_activation(&model->fwc1_fc_1_gate, tmp1, tmp1, ACTIVATION_TANH);
239*a58d3d2aSXin Li
240*a58d3d2aSXin Li compute_generic_conv1d(&model->fwc2_fc_0, tmp2, st->fwc2_state, tmp1, FWC1_FC_0_OUT_SIZE, ACTIVATION_LINEAR);
241*a58d3d2aSXin Li compute_gated_activation(&model->fwc2_fc_1_gate, tmp2, tmp2, ACTIVATION_TANH);
242*a58d3d2aSXin Li
243*a58d3d2aSXin Li compute_generic_conv1d(&model->fwc3_fc_0, tmp1, st->fwc3_state, tmp2, FWC2_FC_0_OUT_SIZE, ACTIVATION_LINEAR);
244*a58d3d2aSXin Li compute_gated_activation(&model->fwc3_fc_1_gate, tmp1, tmp1, ACTIVATION_TANH);
245*a58d3d2aSXin Li
246*a58d3d2aSXin Li compute_generic_conv1d(&model->fwc4_fc_0, tmp2, st->fwc4_state, tmp1, FWC3_FC_0_OUT_SIZE, ACTIVATION_LINEAR);
247*a58d3d2aSXin Li compute_gated_activation(&model->fwc4_fc_1_gate, tmp2, tmp2, ACTIVATION_TANH);
248*a58d3d2aSXin Li
249*a58d3d2aSXin Li compute_generic_conv1d(&model->fwc5_fc_0, tmp1, st->fwc5_state, tmp2, FWC4_FC_0_OUT_SIZE, ACTIVATION_LINEAR);
250*a58d3d2aSXin Li compute_gated_activation(&model->fwc5_fc_1_gate, tmp1, tmp1, ACTIVATION_TANH);
251*a58d3d2aSXin Li
252*a58d3d2aSXin Li compute_generic_conv1d(&model->fwc6_fc_0, tmp2, st->fwc6_state, tmp1, FWC5_FC_0_OUT_SIZE, ACTIVATION_LINEAR);
253*a58d3d2aSXin Li compute_gated_activation(&model->fwc6_fc_1_gate, tmp2, tmp2, ACTIVATION_TANH);
254*a58d3d2aSXin Li
255*a58d3d2aSXin Li compute_generic_conv1d(&model->fwc7_fc_0, tmp1, st->fwc7_state, tmp2, FWC6_FC_0_OUT_SIZE, ACTIVATION_LINEAR);
256*a58d3d2aSXin Li compute_gated_activation(&model->fwc7_fc_1_gate, pcm, tmp1, ACTIVATION_TANH);
257*a58d3d2aSXin Li
258*a58d3d2aSXin Li apply_gain(pcm, c0, &st->last_gain);
259*a58d3d2aSXin Li fwgan_preemphasis(pcm, &st->preemph_mem);
260*a58d3d2aSXin Li fwgan_lpc_syn(pcm, st->syn_mem, lpc, st->last_lpc);
261*a58d3d2aSXin Li fwgan_deemphasis(pcm, &st->deemph_mem);
262*a58d3d2aSXin Li }
263*a58d3d2aSXin Li
fwgan_init(FWGANState * st)264*a58d3d2aSXin Li void fwgan_init(FWGANState *st)
265*a58d3d2aSXin Li {
266*a58d3d2aSXin Li int ret;
267*a58d3d2aSXin Li OPUS_CLEAR(st, 1);
268*a58d3d2aSXin Li ret = init_fwgan(&st->model, fwgan_arrays);
269*a58d3d2aSXin Li celt_assert(ret == 0);
270*a58d3d2aSXin Li /* FIXME: perform arch detection. */
271*a58d3d2aSXin Li }
272*a58d3d2aSXin Li
fwgan_load_model(FWGANState * st,const unsigned char * data,int len)273*a58d3d2aSXin Li int fwgan_load_model(FWGANState *st, const unsigned char *data, int len) {
274*a58d3d2aSXin Li WeightArray *list;
275*a58d3d2aSXin Li int ret;
276*a58d3d2aSXin Li parse_weights(&list, data, len);
277*a58d3d2aSXin Li ret = init_fwgan(&st->model, list);
278*a58d3d2aSXin Li opus_free(list);
279*a58d3d2aSXin Li if (ret == 0) return 0;
280*a58d3d2aSXin Li else return -1;
281*a58d3d2aSXin Li }
282*a58d3d2aSXin Li
fwgan_synthesize_impl(FWGANState * st,float * pcm,const float * lpc,const float * features)283*a58d3d2aSXin Li static void fwgan_synthesize_impl(FWGANState *st, float *pcm, const float *lpc, const float *features)
284*a58d3d2aSXin Li {
285*a58d3d2aSXin Li int subframe;
286*a58d3d2aSXin Li float cond[BFCC_WITH_CORR_UPSAMPLER_FC_OUT_SIZE];
287*a58d3d2aSXin Li double w0;
288*a58d3d2aSXin Li int period;
289*a58d3d2aSXin Li float fwgan_features[NB_FEATURES-1];
290*a58d3d2aSXin Li celt_assert(st->cont_initialized);
291*a58d3d2aSXin Li OPUS_COPY(fwgan_features, features, NB_FEATURES-2);
292*a58d3d2aSXin Li fwgan_features[NB_FEATURES-2] = features[NB_FEATURES-1]+.5;
293*a58d3d2aSXin Li
294*a58d3d2aSXin Li period = (int)floor(.1 + 50*features[NB_BANDS]+100);
295*a58d3d2aSXin Li w0 = 2*M_PI/period;
296*a58d3d2aSXin Li run_fwgan_upsampler(st, cond, fwgan_features);
297*a58d3d2aSXin Li for (subframe=0;subframe<NB_SUBFRAMES;subframe++) {
298*a58d3d2aSXin Li float *sub_cond;
299*a58d3d2aSXin Li sub_cond = &cond[subframe*BFCC_WITH_CORR_UPSAMPLER_FC_OUT_SIZE/4];
300*a58d3d2aSXin Li run_fwgan_subframe(st, &pcm[subframe*SUBFRAME_SIZE], sub_cond, w0, lpc, features[0]);
301*a58d3d2aSXin Li }
302*a58d3d2aSXin Li }
303*a58d3d2aSXin Li
fwgan_synthesize(FWGANState * st,float * pcm,const float * features)304*a58d3d2aSXin Li void fwgan_synthesize(FWGANState *st, float *pcm, const float *features)
305*a58d3d2aSXin Li {
306*a58d3d2aSXin Li float lpc[LPC_ORDER];
307*a58d3d2aSXin Li float new_pcm[FWGAN_FRAME_SIZE];
308*a58d3d2aSXin Li compute_wlpc(lpc, features);
309*a58d3d2aSXin Li fwgan_synthesize_impl(st, new_pcm, lpc, features);
310*a58d3d2aSXin Li /* Handle buffering. */
311*a58d3d2aSXin Li OPUS_COPY(pcm, st->pcm_buf, FWGAN_FRAME_SIZE-SUBFRAME_SIZE);
312*a58d3d2aSXin Li OPUS_COPY(&pcm[FWGAN_FRAME_SIZE-SUBFRAME_SIZE], new_pcm, SUBFRAME_SIZE);
313*a58d3d2aSXin Li OPUS_COPY(st->pcm_buf, &new_pcm[SUBFRAME_SIZE], FWGAN_FRAME_SIZE-SUBFRAME_SIZE);
314*a58d3d2aSXin Li }
315*a58d3d2aSXin Li
fwgan_synthesize_int(FWGANState * st,opus_int16 * pcm,const float * features)316*a58d3d2aSXin Li void fwgan_synthesize_int(FWGANState *st, opus_int16 *pcm, const float *features)
317*a58d3d2aSXin Li {
318*a58d3d2aSXin Li int i;
319*a58d3d2aSXin Li float fpcm[FWGAN_FRAME_SIZE];
320*a58d3d2aSXin Li fwgan_synthesize(st, fpcm, features);
321*a58d3d2aSXin Li for (i=0;i<LPCNET_FRAME_SIZE;i++) pcm[i] = (int)floor(.5 + MIN32(32767, MAX32(-32767, 32768.f*fpcm[i])));
322*a58d3d2aSXin Li }
323