xref: /aosp_15_r20/external/libopus/dnn/osce.c (revision a58d3d2adb790c104798cd88c8a3aff4fa8b82cc)
1*a58d3d2aSXin Li /* Copyright (c) 2023 Amazon
2*a58d3d2aSXin Li    Written by Jan Buethe */
3*a58d3d2aSXin Li /*
4*a58d3d2aSXin Li    Redistribution and use in source and binary forms, with or without
5*a58d3d2aSXin Li    modification, are permitted provided that the following conditions
6*a58d3d2aSXin Li    are met:
7*a58d3d2aSXin Li 
8*a58d3d2aSXin Li    - Redistributions of source code must retain the above copyright
9*a58d3d2aSXin Li    notice, this list of conditions and the following disclaimer.
10*a58d3d2aSXin Li 
11*a58d3d2aSXin Li    - Redistributions in binary form must reproduce the above copyright
12*a58d3d2aSXin Li    notice, this list of conditions and the following disclaimer in the
13*a58d3d2aSXin Li    documentation and/or other materials provided with the distribution.
14*a58d3d2aSXin Li 
15*a58d3d2aSXin Li    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*a58d3d2aSXin Li    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*a58d3d2aSXin Li    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18*a58d3d2aSXin Li    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19*a58d3d2aSXin Li    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20*a58d3d2aSXin Li    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21*a58d3d2aSXin Li    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22*a58d3d2aSXin Li    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23*a58d3d2aSXin Li    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24*a58d3d2aSXin Li    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*a58d3d2aSXin Li    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*a58d3d2aSXin Li */
27*a58d3d2aSXin Li 
28*a58d3d2aSXin Li #ifdef HAVE_CONFIG_H
29*a58d3d2aSXin Li #include "config.h"
30*a58d3d2aSXin Li #endif
31*a58d3d2aSXin Li 
32*a58d3d2aSXin Li 
33*a58d3d2aSXin Li #include <math.h>
34*a58d3d2aSXin Li #include "osce.h"
35*a58d3d2aSXin Li #include "osce_features.h"
36*a58d3d2aSXin Li #include "os_support.h"
37*a58d3d2aSXin Li #include "nndsp.h"
38*a58d3d2aSXin Li #include "float_cast.h"
39*a58d3d2aSXin Li #include "arch.h"
40*a58d3d2aSXin Li 
41*a58d3d2aSXin Li #ifdef OSCE_DEBUG
42*a58d3d2aSXin Li #include <stdio.h>
43*a58d3d2aSXin Li /*#define WRITE_FEATURES*/
44*a58d3d2aSXin Li /*#define DEBUG_LACE*/
45*a58d3d2aSXin Li /*#define DEBUG_NOLACE*/
46*a58d3d2aSXin Li #define FINIT(fid, name, mode) do{if (fid == NULL) {fid = fopen(name, mode);}} while(0)
47*a58d3d2aSXin Li #endif
48*a58d3d2aSXin Li 
49*a58d3d2aSXin Li #ifdef ENABLE_OSCE_TRAINING_DATA
50*a58d3d2aSXin Li #include <stdio.h>
51*a58d3d2aSXin Li #endif
52*a58d3d2aSXin Li 
53*a58d3d2aSXin Li #define CLIP(a, min, max) (((a) < (min) ? (min) : (a)) > (max) ? (max) : (a))
54*a58d3d2aSXin Li 
55*a58d3d2aSXin Li extern const WeightArray lacelayers_arrays[];
56*a58d3d2aSXin Li extern const WeightArray nolacelayers_arrays[];
57*a58d3d2aSXin Li 
58*a58d3d2aSXin Li /* LACE */
59*a58d3d2aSXin Li 
60*a58d3d2aSXin Li #ifndef DISABLE_LACE
61*a58d3d2aSXin Li 
compute_lace_numbits_embedding(float * emb,float numbits,int dim,float min_val,float max_val,int logscale)62*a58d3d2aSXin Li static void compute_lace_numbits_embedding(float *emb, float numbits, int dim, float min_val, float max_val, int logscale)
63*a58d3d2aSXin Li {
64*a58d3d2aSXin Li     float x;
65*a58d3d2aSXin Li     (void) dim;
66*a58d3d2aSXin Li 
67*a58d3d2aSXin Li     numbits = logscale ? log(numbits) : numbits;
68*a58d3d2aSXin Li     x = CLIP(numbits, min_val, max_val) - (max_val + min_val) / 2;
69*a58d3d2aSXin Li 
70*a58d3d2aSXin Li     emb[0] = sin(x * LACE_NUMBITS_SCALE_0 - 0.5f);
71*a58d3d2aSXin Li     emb[1] = sin(x * LACE_NUMBITS_SCALE_1 - 0.5f);
72*a58d3d2aSXin Li     emb[2] = sin(x * LACE_NUMBITS_SCALE_2 - 0.5f);
73*a58d3d2aSXin Li     emb[3] = sin(x * LACE_NUMBITS_SCALE_3 - 0.5f);
74*a58d3d2aSXin Li     emb[4] = sin(x * LACE_NUMBITS_SCALE_4 - 0.5f);
75*a58d3d2aSXin Li     emb[5] = sin(x * LACE_NUMBITS_SCALE_5 - 0.5f);
76*a58d3d2aSXin Li     emb[6] = sin(x * LACE_NUMBITS_SCALE_6 - 0.5f);
77*a58d3d2aSXin Li     emb[7] = sin(x * LACE_NUMBITS_SCALE_7 - 0.5f);
78*a58d3d2aSXin Li }
79*a58d3d2aSXin Li 
80*a58d3d2aSXin Li 
init_lace(LACE * hLACE,const WeightArray * weights)81*a58d3d2aSXin Li static int init_lace(LACE *hLACE, const WeightArray *weights)
82*a58d3d2aSXin Li {
83*a58d3d2aSXin Li     int ret = 0;
84*a58d3d2aSXin Li     OPUS_CLEAR(hLACE, 1);
85*a58d3d2aSXin Li     celt_assert(weights != NULL);
86*a58d3d2aSXin Li 
87*a58d3d2aSXin Li     ret = init_lacelayers(&hLACE->layers, weights);
88*a58d3d2aSXin Li 
89*a58d3d2aSXin Li     compute_overlap_window(hLACE->window, LACE_OVERLAP_SIZE);
90*a58d3d2aSXin Li 
91*a58d3d2aSXin Li     return ret;
92*a58d3d2aSXin Li }
93*a58d3d2aSXin Li 
reset_lace_state(LACEState * state)94*a58d3d2aSXin Li static void reset_lace_state(LACEState *state)
95*a58d3d2aSXin Li {
96*a58d3d2aSXin Li     OPUS_CLEAR(state, 1);
97*a58d3d2aSXin Li 
98*a58d3d2aSXin Li     init_adacomb_state(&state->cf1_state);
99*a58d3d2aSXin Li     init_adacomb_state(&state->cf2_state);
100*a58d3d2aSXin Li     init_adaconv_state(&state->af1_state);
101*a58d3d2aSXin Li }
102*a58d3d2aSXin Li 
lace_feature_net(LACE * hLACE,LACEState * state,float * output,const float * features,const float * numbits,const int * periods,int arch)103*a58d3d2aSXin Li static void lace_feature_net(
104*a58d3d2aSXin Li     LACE *hLACE,
105*a58d3d2aSXin Li     LACEState *state,
106*a58d3d2aSXin Li     float *output,
107*a58d3d2aSXin Li     const float *features,
108*a58d3d2aSXin Li     const float *numbits,
109*a58d3d2aSXin Li     const int *periods,
110*a58d3d2aSXin Li     int arch
111*a58d3d2aSXin Li )
112*a58d3d2aSXin Li {
113*a58d3d2aSXin Li     float input_buffer[4 * IMAX(LACE_COND_DIM, LACE_HIDDEN_FEATURE_DIM)];
114*a58d3d2aSXin Li     float output_buffer[4 * IMAX(LACE_COND_DIM, LACE_HIDDEN_FEATURE_DIM)];
115*a58d3d2aSXin Li     float numbits_embedded[2 * LACE_NUMBITS_EMBEDDING_DIM];
116*a58d3d2aSXin Li     int i_subframe;
117*a58d3d2aSXin Li 
118*a58d3d2aSXin Li     compute_lace_numbits_embedding(numbits_embedded, numbits[0], LACE_NUMBITS_EMBEDDING_DIM,
119*a58d3d2aSXin Li         log(LACE_NUMBITS_RANGE_LOW), log(LACE_NUMBITS_RANGE_HIGH), 1);
120*a58d3d2aSXin Li     compute_lace_numbits_embedding(numbits_embedded + LACE_NUMBITS_EMBEDDING_DIM, numbits[1], LACE_NUMBITS_EMBEDDING_DIM,
121*a58d3d2aSXin Li         log(LACE_NUMBITS_RANGE_LOW), log(LACE_NUMBITS_RANGE_HIGH), 1);
122*a58d3d2aSXin Li 
123*a58d3d2aSXin Li     /* scaling and dimensionality reduction */
124*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe ++)
125*a58d3d2aSXin Li     {
126*a58d3d2aSXin Li         OPUS_COPY(input_buffer, features + i_subframe * LACE_NUM_FEATURES, LACE_NUM_FEATURES);
127*a58d3d2aSXin Li         OPUS_COPY(input_buffer + LACE_NUM_FEATURES, hLACE->layers.lace_pitch_embedding.float_weights + periods[i_subframe] * LACE_PITCH_EMBEDDING_DIM, LACE_PITCH_EMBEDDING_DIM);
128*a58d3d2aSXin Li         OPUS_COPY(input_buffer + LACE_NUM_FEATURES + LACE_PITCH_EMBEDDING_DIM, numbits_embedded, 2 * LACE_NUMBITS_EMBEDDING_DIM);
129*a58d3d2aSXin Li 
130*a58d3d2aSXin Li         compute_generic_conv1d(
131*a58d3d2aSXin Li             &hLACE->layers.lace_fnet_conv1,
132*a58d3d2aSXin Li             output_buffer + i_subframe * LACE_HIDDEN_FEATURE_DIM,
133*a58d3d2aSXin Li             NULL,
134*a58d3d2aSXin Li             input_buffer,
135*a58d3d2aSXin Li             LACE_NUM_FEATURES + LACE_PITCH_EMBEDDING_DIM + 2 * LACE_NUMBITS_EMBEDDING_DIM,
136*a58d3d2aSXin Li             ACTIVATION_TANH,
137*a58d3d2aSXin Li             arch);
138*a58d3d2aSXin Li     }
139*a58d3d2aSXin Li 
140*a58d3d2aSXin Li     /* subframe accumulation */
141*a58d3d2aSXin Li     OPUS_COPY(input_buffer, output_buffer, 4 * LACE_HIDDEN_FEATURE_DIM);
142*a58d3d2aSXin Li     compute_generic_conv1d(
143*a58d3d2aSXin Li         &hLACE->layers.lace_fnet_conv2,
144*a58d3d2aSXin Li         output_buffer,
145*a58d3d2aSXin Li         state->feature_net_conv2_state,
146*a58d3d2aSXin Li         input_buffer,
147*a58d3d2aSXin Li         4 * LACE_HIDDEN_FEATURE_DIM,
148*a58d3d2aSXin Li         ACTIVATION_TANH,
149*a58d3d2aSXin Li         arch
150*a58d3d2aSXin Li     );
151*a58d3d2aSXin Li 
152*a58d3d2aSXin Li     /* tconv upsampling */
153*a58d3d2aSXin Li     OPUS_COPY(input_buffer, output_buffer, 4 * LACE_COND_DIM);
154*a58d3d2aSXin Li     compute_generic_dense(
155*a58d3d2aSXin Li         &hLACE->layers.lace_fnet_tconv,
156*a58d3d2aSXin Li         output_buffer,
157*a58d3d2aSXin Li         input_buffer,
158*a58d3d2aSXin Li         ACTIVATION_TANH,
159*a58d3d2aSXin Li         arch
160*a58d3d2aSXin Li     );
161*a58d3d2aSXin Li 
162*a58d3d2aSXin Li     /* GRU */
163*a58d3d2aSXin Li     OPUS_COPY(input_buffer, output_buffer, 4 * LACE_COND_DIM);
164*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
165*a58d3d2aSXin Li     {
166*a58d3d2aSXin Li         compute_generic_gru(
167*a58d3d2aSXin Li             &hLACE->layers.lace_fnet_gru_input,
168*a58d3d2aSXin Li             &hLACE->layers.lace_fnet_gru_recurrent,
169*a58d3d2aSXin Li             state->feature_net_gru_state,
170*a58d3d2aSXin Li             input_buffer + i_subframe * LACE_COND_DIM,
171*a58d3d2aSXin Li             arch
172*a58d3d2aSXin Li         );
173*a58d3d2aSXin Li         OPUS_COPY(output + i_subframe * LACE_COND_DIM, state->feature_net_gru_state, LACE_COND_DIM);
174*a58d3d2aSXin Li     }
175*a58d3d2aSXin Li }
176*a58d3d2aSXin Li 
177*a58d3d2aSXin Li 
lace_process_20ms_frame(LACE * hLACE,LACEState * state,float * x_out,const float * x_in,const float * features,const float * numbits,const int * periods,int arch)178*a58d3d2aSXin Li static void lace_process_20ms_frame(
179*a58d3d2aSXin Li     LACE* hLACE,
180*a58d3d2aSXin Li     LACEState *state,
181*a58d3d2aSXin Li     float *x_out,
182*a58d3d2aSXin Li     const float *x_in,
183*a58d3d2aSXin Li     const float *features,
184*a58d3d2aSXin Li     const float *numbits,
185*a58d3d2aSXin Li     const int *periods,
186*a58d3d2aSXin Li     int arch
187*a58d3d2aSXin Li )
188*a58d3d2aSXin Li {
189*a58d3d2aSXin Li     float feature_buffer[4 * LACE_COND_DIM];
190*a58d3d2aSXin Li     float output_buffer[4 * LACE_FRAME_SIZE];
191*a58d3d2aSXin Li     int i_subframe, i_sample;
192*a58d3d2aSXin Li 
193*a58d3d2aSXin Li #ifdef DEBUG_LACE
194*a58d3d2aSXin Li     static FILE *f_features=NULL, *f_encfeatures=NULL, *f_xin=NULL, *f_xpreemph=NULL, *f_postcf1=NULL;
195*a58d3d2aSXin Li     static FILE *f_postcf2=NULL, *f_postaf1=NULL, *f_xdeemph, *f_numbits, *f_periods;
196*a58d3d2aSXin Li 
197*a58d3d2aSXin Li 
198*a58d3d2aSXin Li     FINIT(f_features, "debug/c_features.f32", "wb");
199*a58d3d2aSXin Li     FINIT(f_encfeatures, "debug/c_encoded_features.f32", "wb");
200*a58d3d2aSXin Li     FINIT(f_xin, "debug/c_x_in.f32", "wb");
201*a58d3d2aSXin Li     FINIT(f_xpreemph, "debug/c_xpreemph.f32", "wb");
202*a58d3d2aSXin Li     FINIT(f_xdeemph, "debug/c_xdeemph.f32", "wb");
203*a58d3d2aSXin Li     FINIT(f_postcf1, "debug/c_post_cf1.f32", "wb");
204*a58d3d2aSXin Li     FINIT(f_postcf2, "debug/c_post_cf2.f32", "wb");
205*a58d3d2aSXin Li     FINIT(f_postaf1, "debug/c_post_af1.f32", "wb");
206*a58d3d2aSXin Li     FINIT(f_numbits, "debug/c_numbits.f32", "wb");
207*a58d3d2aSXin Li     FINIT(f_periods, "debug/c_periods.s32", "wb");
208*a58d3d2aSXin Li 
209*a58d3d2aSXin Li     fwrite(x_in, sizeof(*x_in), 4 * LACE_FRAME_SIZE, f_xin);
210*a58d3d2aSXin Li     fwrite(numbits, sizeof(*numbits), 2, f_numbits);
211*a58d3d2aSXin Li     fwrite(periods, sizeof(*periods), 4, f_periods);
212*a58d3d2aSXin Li #endif
213*a58d3d2aSXin Li 
214*a58d3d2aSXin Li     /* pre-emphasis */
215*a58d3d2aSXin Li     for (i_sample = 0; i_sample < 4 * LACE_FRAME_SIZE; i_sample ++)
216*a58d3d2aSXin Li     {
217*a58d3d2aSXin Li         output_buffer[i_sample] = x_in[i_sample] - LACE_PREEMPH * state->preemph_mem;
218*a58d3d2aSXin Li         state->preemph_mem = x_in[i_sample];
219*a58d3d2aSXin Li     }
220*a58d3d2aSXin Li 
221*a58d3d2aSXin Li     /* run feature encoder */
222*a58d3d2aSXin Li     lace_feature_net(hLACE, state, feature_buffer, features, numbits, periods, arch);
223*a58d3d2aSXin Li #ifdef DEBUG_LACE
224*a58d3d2aSXin Li     fwrite(features, sizeof(*features), 4 * LACE_NUM_FEATURES, f_features);
225*a58d3d2aSXin Li     fwrite(feature_buffer, sizeof(*feature_buffer), 4 * LACE_COND_DIM, f_encfeatures);
226*a58d3d2aSXin Li     fwrite(output_buffer, sizeof(float), 4 * LACE_FRAME_SIZE, f_xpreemph);
227*a58d3d2aSXin Li #endif
228*a58d3d2aSXin Li 
229*a58d3d2aSXin Li     /* 1st comb filtering stage */
230*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
231*a58d3d2aSXin Li     {
232*a58d3d2aSXin Li         adacomb_process_frame(
233*a58d3d2aSXin Li             &state->cf1_state,
234*a58d3d2aSXin Li             output_buffer + i_subframe * LACE_FRAME_SIZE,
235*a58d3d2aSXin Li             output_buffer + i_subframe * LACE_FRAME_SIZE,
236*a58d3d2aSXin Li             feature_buffer + i_subframe * LACE_COND_DIM,
237*a58d3d2aSXin Li             &hLACE->layers.lace_cf1_kernel,
238*a58d3d2aSXin Li             &hLACE->layers.lace_cf1_gain,
239*a58d3d2aSXin Li             &hLACE->layers.lace_cf1_global_gain,
240*a58d3d2aSXin Li             periods[i_subframe],
241*a58d3d2aSXin Li             LACE_COND_DIM,
242*a58d3d2aSXin Li             LACE_FRAME_SIZE,
243*a58d3d2aSXin Li             LACE_OVERLAP_SIZE,
244*a58d3d2aSXin Li             LACE_CF1_KERNEL_SIZE,
245*a58d3d2aSXin Li             LACE_CF1_LEFT_PADDING,
246*a58d3d2aSXin Li             LACE_CF1_FILTER_GAIN_A,
247*a58d3d2aSXin Li             LACE_CF1_FILTER_GAIN_B,
248*a58d3d2aSXin Li             LACE_CF1_LOG_GAIN_LIMIT,
249*a58d3d2aSXin Li             hLACE->window,
250*a58d3d2aSXin Li             arch);
251*a58d3d2aSXin Li     }
252*a58d3d2aSXin Li 
253*a58d3d2aSXin Li #ifdef DEBUG_LACE
254*a58d3d2aSXin Li     fwrite(output_buffer, sizeof(float), 4 * LACE_FRAME_SIZE, f_postcf1);
255*a58d3d2aSXin Li #endif
256*a58d3d2aSXin Li 
257*a58d3d2aSXin Li     /* 2nd comb filtering stage */
258*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
259*a58d3d2aSXin Li     {
260*a58d3d2aSXin Li         adacomb_process_frame(
261*a58d3d2aSXin Li             &state->cf2_state,
262*a58d3d2aSXin Li             output_buffer + i_subframe * LACE_FRAME_SIZE,
263*a58d3d2aSXin Li             output_buffer + i_subframe * LACE_FRAME_SIZE,
264*a58d3d2aSXin Li             feature_buffer + i_subframe * LACE_COND_DIM,
265*a58d3d2aSXin Li             &hLACE->layers.lace_cf2_kernel,
266*a58d3d2aSXin Li             &hLACE->layers.lace_cf2_gain,
267*a58d3d2aSXin Li             &hLACE->layers.lace_cf2_global_gain,
268*a58d3d2aSXin Li             periods[i_subframe],
269*a58d3d2aSXin Li             LACE_COND_DIM,
270*a58d3d2aSXin Li             LACE_FRAME_SIZE,
271*a58d3d2aSXin Li             LACE_OVERLAP_SIZE,
272*a58d3d2aSXin Li             LACE_CF2_KERNEL_SIZE,
273*a58d3d2aSXin Li             LACE_CF2_LEFT_PADDING,
274*a58d3d2aSXin Li             LACE_CF2_FILTER_GAIN_A,
275*a58d3d2aSXin Li             LACE_CF2_FILTER_GAIN_B,
276*a58d3d2aSXin Li             LACE_CF2_LOG_GAIN_LIMIT,
277*a58d3d2aSXin Li             hLACE->window,
278*a58d3d2aSXin Li             arch);
279*a58d3d2aSXin Li     }
280*a58d3d2aSXin Li #ifdef DEBUG_LACE
281*a58d3d2aSXin Li     fwrite(output_buffer, sizeof(float), 4 * LACE_FRAME_SIZE, f_postcf2);
282*a58d3d2aSXin Li #endif
283*a58d3d2aSXin Li 
284*a58d3d2aSXin Li     /* final adaptive filtering stage */
285*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
286*a58d3d2aSXin Li     {
287*a58d3d2aSXin Li         adaconv_process_frame(
288*a58d3d2aSXin Li             &state->af1_state,
289*a58d3d2aSXin Li             output_buffer + i_subframe * LACE_FRAME_SIZE,
290*a58d3d2aSXin Li             output_buffer + i_subframe * LACE_FRAME_SIZE,
291*a58d3d2aSXin Li             feature_buffer + i_subframe * LACE_COND_DIM,
292*a58d3d2aSXin Li             &hLACE->layers.lace_af1_kernel,
293*a58d3d2aSXin Li             &hLACE->layers.lace_af1_gain,
294*a58d3d2aSXin Li             LACE_COND_DIM,
295*a58d3d2aSXin Li             LACE_FRAME_SIZE,
296*a58d3d2aSXin Li             LACE_OVERLAP_SIZE,
297*a58d3d2aSXin Li             LACE_AF1_IN_CHANNELS,
298*a58d3d2aSXin Li             LACE_AF1_OUT_CHANNELS,
299*a58d3d2aSXin Li             LACE_AF1_KERNEL_SIZE,
300*a58d3d2aSXin Li             LACE_AF1_LEFT_PADDING,
301*a58d3d2aSXin Li             LACE_AF1_FILTER_GAIN_A,
302*a58d3d2aSXin Li             LACE_AF1_FILTER_GAIN_B,
303*a58d3d2aSXin Li             LACE_AF1_SHAPE_GAIN,
304*a58d3d2aSXin Li             hLACE->window,
305*a58d3d2aSXin Li             arch);
306*a58d3d2aSXin Li     }
307*a58d3d2aSXin Li #ifdef DEBUG_LACE
308*a58d3d2aSXin Li     fwrite(output_buffer, sizeof(float), 4 * LACE_FRAME_SIZE, f_postaf1);
309*a58d3d2aSXin Li #endif
310*a58d3d2aSXin Li 
311*a58d3d2aSXin Li     /* de-emphasis */
312*a58d3d2aSXin Li     for (i_sample = 0; i_sample < 4 * LACE_FRAME_SIZE; i_sample ++)
313*a58d3d2aSXin Li     {
314*a58d3d2aSXin Li         x_out[i_sample] = output_buffer[i_sample] + LACE_PREEMPH * state->deemph_mem;
315*a58d3d2aSXin Li         state->deemph_mem = x_out[i_sample];
316*a58d3d2aSXin Li     }
317*a58d3d2aSXin Li #ifdef DEBUG_LACE
318*a58d3d2aSXin Li     fwrite(x_out, sizeof(float), 4 * LACE_FRAME_SIZE, f_xdeemph);
319*a58d3d2aSXin Li #endif
320*a58d3d2aSXin Li }
321*a58d3d2aSXin Li 
322*a58d3d2aSXin Li #endif /* #ifndef DISABLE_LACE */
323*a58d3d2aSXin Li 
324*a58d3d2aSXin Li 
325*a58d3d2aSXin Li /* NoLACE */
326*a58d3d2aSXin Li #ifndef DISABLE_NOLACE
327*a58d3d2aSXin Li 
compute_nolace_numbits_embedding(float * emb,float numbits,int dim,float min_val,float max_val,int logscale)328*a58d3d2aSXin Li static void compute_nolace_numbits_embedding(float *emb, float numbits, int dim, float min_val, float max_val, int logscale)
329*a58d3d2aSXin Li {
330*a58d3d2aSXin Li     float x;
331*a58d3d2aSXin Li     (void) dim;
332*a58d3d2aSXin Li 
333*a58d3d2aSXin Li     numbits = logscale ? log(numbits) : numbits;
334*a58d3d2aSXin Li     x = CLIP(numbits, min_val, max_val) - (max_val + min_val) / 2;
335*a58d3d2aSXin Li 
336*a58d3d2aSXin Li     emb[0] = sin(x * NOLACE_NUMBITS_SCALE_0 - 0.5f);
337*a58d3d2aSXin Li     emb[1] = sin(x * NOLACE_NUMBITS_SCALE_1 - 0.5f);
338*a58d3d2aSXin Li     emb[2] = sin(x * NOLACE_NUMBITS_SCALE_2 - 0.5f);
339*a58d3d2aSXin Li     emb[3] = sin(x * NOLACE_NUMBITS_SCALE_3 - 0.5f);
340*a58d3d2aSXin Li     emb[4] = sin(x * NOLACE_NUMBITS_SCALE_4 - 0.5f);
341*a58d3d2aSXin Li     emb[5] = sin(x * NOLACE_NUMBITS_SCALE_5 - 0.5f);
342*a58d3d2aSXin Li     emb[6] = sin(x * NOLACE_NUMBITS_SCALE_6 - 0.5f);
343*a58d3d2aSXin Li     emb[7] = sin(x * NOLACE_NUMBITS_SCALE_7 - 0.5f);
344*a58d3d2aSXin Li }
345*a58d3d2aSXin Li 
init_nolace(NoLACE * hNoLACE,const WeightArray * weights)346*a58d3d2aSXin Li static int init_nolace(NoLACE *hNoLACE, const WeightArray *weights)
347*a58d3d2aSXin Li {
348*a58d3d2aSXin Li     int ret = 0;
349*a58d3d2aSXin Li     OPUS_CLEAR(hNoLACE, 1);
350*a58d3d2aSXin Li     celt_assert(weights != NULL);
351*a58d3d2aSXin Li 
352*a58d3d2aSXin Li     ret = init_nolacelayers(&hNoLACE->layers, weights);
353*a58d3d2aSXin Li 
354*a58d3d2aSXin Li     compute_overlap_window(hNoLACE->window, NOLACE_OVERLAP_SIZE);
355*a58d3d2aSXin Li 
356*a58d3d2aSXin Li     return ret;
357*a58d3d2aSXin Li }
358*a58d3d2aSXin Li 
reset_nolace_state(NoLACEState * state)359*a58d3d2aSXin Li static void reset_nolace_state(NoLACEState *state)
360*a58d3d2aSXin Li {
361*a58d3d2aSXin Li     OPUS_CLEAR(state, 1);
362*a58d3d2aSXin Li 
363*a58d3d2aSXin Li     init_adacomb_state(&state->cf1_state);
364*a58d3d2aSXin Li     init_adacomb_state(&state->cf2_state);
365*a58d3d2aSXin Li     init_adaconv_state(&state->af1_state);
366*a58d3d2aSXin Li     init_adaconv_state(&state->af2_state);
367*a58d3d2aSXin Li     init_adaconv_state(&state->af3_state);
368*a58d3d2aSXin Li     init_adaconv_state(&state->af4_state);
369*a58d3d2aSXin Li     init_adashape_state(&state->tdshape1_state);
370*a58d3d2aSXin Li     init_adashape_state(&state->tdshape2_state);
371*a58d3d2aSXin Li     init_adashape_state(&state->tdshape3_state);
372*a58d3d2aSXin Li }
373*a58d3d2aSXin Li 
nolace_feature_net(NoLACE * hNoLACE,NoLACEState * state,float * output,const float * features,const float * numbits,const int * periods,int arch)374*a58d3d2aSXin Li static void nolace_feature_net(
375*a58d3d2aSXin Li     NoLACE *hNoLACE,
376*a58d3d2aSXin Li     NoLACEState *state,
377*a58d3d2aSXin Li     float *output,
378*a58d3d2aSXin Li     const float *features,
379*a58d3d2aSXin Li     const float *numbits,
380*a58d3d2aSXin Li     const int *periods,
381*a58d3d2aSXin Li     int arch
382*a58d3d2aSXin Li )
383*a58d3d2aSXin Li {
384*a58d3d2aSXin Li     float input_buffer[4 * IMAX(NOLACE_COND_DIM, NOLACE_HIDDEN_FEATURE_DIM)];
385*a58d3d2aSXin Li     float output_buffer[4 * IMAX(NOLACE_COND_DIM, NOLACE_HIDDEN_FEATURE_DIM)];
386*a58d3d2aSXin Li     float numbits_embedded[2 * NOLACE_NUMBITS_EMBEDDING_DIM];
387*a58d3d2aSXin Li     int i_subframe;
388*a58d3d2aSXin Li 
389*a58d3d2aSXin Li     compute_nolace_numbits_embedding(numbits_embedded, numbits[0], NOLACE_NUMBITS_EMBEDDING_DIM,
390*a58d3d2aSXin Li         log(NOLACE_NUMBITS_RANGE_LOW), log(NOLACE_NUMBITS_RANGE_HIGH), 1);
391*a58d3d2aSXin Li     compute_nolace_numbits_embedding(numbits_embedded + NOLACE_NUMBITS_EMBEDDING_DIM, numbits[1], NOLACE_NUMBITS_EMBEDDING_DIM,
392*a58d3d2aSXin Li         log(NOLACE_NUMBITS_RANGE_LOW), log(NOLACE_NUMBITS_RANGE_HIGH), 1);
393*a58d3d2aSXin Li 
394*a58d3d2aSXin Li     /* scaling and dimensionality reduction */
395*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe ++)
396*a58d3d2aSXin Li     {
397*a58d3d2aSXin Li         OPUS_COPY(input_buffer, features + i_subframe * NOLACE_NUM_FEATURES, NOLACE_NUM_FEATURES);
398*a58d3d2aSXin Li         OPUS_COPY(input_buffer + NOLACE_NUM_FEATURES, hNoLACE->layers.nolace_pitch_embedding.float_weights + periods[i_subframe] * NOLACE_PITCH_EMBEDDING_DIM, NOLACE_PITCH_EMBEDDING_DIM);
399*a58d3d2aSXin Li         OPUS_COPY(input_buffer + NOLACE_NUM_FEATURES + NOLACE_PITCH_EMBEDDING_DIM, numbits_embedded, 2 * NOLACE_NUMBITS_EMBEDDING_DIM);
400*a58d3d2aSXin Li 
401*a58d3d2aSXin Li         compute_generic_conv1d(
402*a58d3d2aSXin Li             &hNoLACE->layers.nolace_fnet_conv1,
403*a58d3d2aSXin Li             output_buffer + i_subframe * NOLACE_HIDDEN_FEATURE_DIM,
404*a58d3d2aSXin Li             NULL,
405*a58d3d2aSXin Li             input_buffer,
406*a58d3d2aSXin Li             NOLACE_NUM_FEATURES + NOLACE_PITCH_EMBEDDING_DIM + 2 * NOLACE_NUMBITS_EMBEDDING_DIM,
407*a58d3d2aSXin Li             ACTIVATION_TANH,
408*a58d3d2aSXin Li             arch);
409*a58d3d2aSXin Li     }
410*a58d3d2aSXin Li 
411*a58d3d2aSXin Li     /* subframe accumulation */
412*a58d3d2aSXin Li     OPUS_COPY(input_buffer, output_buffer, 4 * NOLACE_HIDDEN_FEATURE_DIM);
413*a58d3d2aSXin Li     compute_generic_conv1d(
414*a58d3d2aSXin Li         &hNoLACE->layers.nolace_fnet_conv2,
415*a58d3d2aSXin Li         output_buffer,
416*a58d3d2aSXin Li         state->feature_net_conv2_state,
417*a58d3d2aSXin Li         input_buffer,
418*a58d3d2aSXin Li         4 * NOLACE_HIDDEN_FEATURE_DIM,
419*a58d3d2aSXin Li         ACTIVATION_TANH,
420*a58d3d2aSXin Li         arch
421*a58d3d2aSXin Li     );
422*a58d3d2aSXin Li 
423*a58d3d2aSXin Li     /* tconv upsampling */
424*a58d3d2aSXin Li     OPUS_COPY(input_buffer, output_buffer, 4 * NOLACE_COND_DIM);
425*a58d3d2aSXin Li     compute_generic_dense(
426*a58d3d2aSXin Li         &hNoLACE->layers.nolace_fnet_tconv,
427*a58d3d2aSXin Li         output_buffer,
428*a58d3d2aSXin Li         input_buffer,
429*a58d3d2aSXin Li         ACTIVATION_TANH,
430*a58d3d2aSXin Li         arch
431*a58d3d2aSXin Li     );
432*a58d3d2aSXin Li 
433*a58d3d2aSXin Li     /* GRU */
434*a58d3d2aSXin Li     OPUS_COPY(input_buffer, output_buffer, 4 * NOLACE_COND_DIM);
435*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
436*a58d3d2aSXin Li     {
437*a58d3d2aSXin Li         compute_generic_gru(
438*a58d3d2aSXin Li             &hNoLACE->layers.nolace_fnet_gru_input,
439*a58d3d2aSXin Li             &hNoLACE->layers.nolace_fnet_gru_recurrent,
440*a58d3d2aSXin Li             state->feature_net_gru_state,
441*a58d3d2aSXin Li             input_buffer + i_subframe * NOLACE_COND_DIM,
442*a58d3d2aSXin Li             arch
443*a58d3d2aSXin Li         );
444*a58d3d2aSXin Li         OPUS_COPY(output + i_subframe * NOLACE_COND_DIM, state->feature_net_gru_state, NOLACE_COND_DIM);
445*a58d3d2aSXin Li     }
446*a58d3d2aSXin Li }
447*a58d3d2aSXin Li 
448*a58d3d2aSXin Li 
nolace_process_20ms_frame(NoLACE * hNoLACE,NoLACEState * state,float * x_out,const float * x_in,const float * features,const float * numbits,const int * periods,int arch)449*a58d3d2aSXin Li static void nolace_process_20ms_frame(
450*a58d3d2aSXin Li     NoLACE* hNoLACE,
451*a58d3d2aSXin Li     NoLACEState *state,
452*a58d3d2aSXin Li     float *x_out,
453*a58d3d2aSXin Li     const float *x_in,
454*a58d3d2aSXin Li     const float *features,
455*a58d3d2aSXin Li     const float *numbits,
456*a58d3d2aSXin Li     const int *periods,
457*a58d3d2aSXin Li     int arch
458*a58d3d2aSXin Li )
459*a58d3d2aSXin Li {
460*a58d3d2aSXin Li     float feature_buffer[4 * NOLACE_COND_DIM];
461*a58d3d2aSXin Li     float feature_transform_buffer[4 * NOLACE_COND_DIM];
462*a58d3d2aSXin Li     float x_buffer1[8 * NOLACE_FRAME_SIZE];
463*a58d3d2aSXin Li     float x_buffer2[8 * NOLACE_FRAME_SIZE];
464*a58d3d2aSXin Li     int i_subframe, i_sample;
465*a58d3d2aSXin Li     NOLACELayers *layers = &hNoLACE->layers;
466*a58d3d2aSXin Li 
467*a58d3d2aSXin Li #ifdef DEBUG_NOLACE
468*a58d3d2aSXin Li     static FILE *f_features=NULL, *f_encfeatures=NULL, *f_xin=NULL, *f_xpreemph=NULL, *f_postcf1=NULL;
469*a58d3d2aSXin Li     static FILE *f_postcf2=NULL, *f_postaf1=NULL, *f_xdeemph, *f_numbits, *f_periods;
470*a58d3d2aSXin Li     static FILE *f_ffpostcf1, *f_fpostcf2, *f_fpostaf1;
471*a58d3d2aSXin Li 
472*a58d3d2aSXin Li 
473*a58d3d2aSXin Li     FINIT(f_features, "debug/c_features.f32", "wb");
474*a58d3d2aSXin Li     FINIT(f_encfeatures, "debug/c_encoded_features.f32", "wb");
475*a58d3d2aSXin Li     FINIT(f_xin, "debug/c_x_in.f32", "wb");
476*a58d3d2aSXin Li     FINIT(f_xpreemph, "debug/c_xpreemph.f32", "wb");
477*a58d3d2aSXin Li     FINIT(f_xdeemph, "debug/c_xdeemph.f32", "wb");
478*a58d3d2aSXin Li     FINIT(f_postcf1, "debug/c_post_cf1.f32", "wb");
479*a58d3d2aSXin Li     FINIT(f_postcf2, "debug/c_post_cf2.f32", "wb");
480*a58d3d2aSXin Li     FINIT(f_postaf1, "debug/c_post_af1.f32", "wb");
481*a58d3d2aSXin Li     FINIT(f_numbits, "debug/c_numbits.f32", "wb");
482*a58d3d2aSXin Li     FINIT(f_periods, "debug/c_periods.s32", "wb");
483*a58d3d2aSXin Li 
484*a58d3d2aSXin Li     fwrite(x_in, sizeof(*x_in), 4 * NOLACE_FRAME_SIZE, f_xin);
485*a58d3d2aSXin Li     fwrite(numbits, sizeof(*numbits), 2, f_numbits);
486*a58d3d2aSXin Li     fwrite(periods, sizeof(*periods), 4, f_periods);
487*a58d3d2aSXin Li #endif
488*a58d3d2aSXin Li 
489*a58d3d2aSXin Li     /* pre-emphasis */
490*a58d3d2aSXin Li     for (i_sample = 0; i_sample < 4 * NOLACE_FRAME_SIZE; i_sample ++)
491*a58d3d2aSXin Li     {
492*a58d3d2aSXin Li         x_buffer1[i_sample] = x_in[i_sample] - NOLACE_PREEMPH * state->preemph_mem;
493*a58d3d2aSXin Li         state->preemph_mem = x_in[i_sample];
494*a58d3d2aSXin Li     }
495*a58d3d2aSXin Li 
496*a58d3d2aSXin Li     /* run feature encoder */
497*a58d3d2aSXin Li     nolace_feature_net(hNoLACE, state, feature_buffer, features, numbits, periods, arch);
498*a58d3d2aSXin Li #ifdef DEBUG_NOLACE
499*a58d3d2aSXin Li     fwrite(features, sizeof(*features), 4 * NOLACE_NUM_FEATURES, f_features);
500*a58d3d2aSXin Li     fwrite(feature_buffer, sizeof(*feature_buffer), 4 * NOLACE_COND_DIM, f_encfeatures);
501*a58d3d2aSXin Li     fwrite(output_buffer, sizeof(float), 4 * NOLACE_FRAME_SIZE, f_xpreemph);
502*a58d3d2aSXin Li #endif
503*a58d3d2aSXin Li 
504*a58d3d2aSXin Li     /* 1st comb filtering stage */
505*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
506*a58d3d2aSXin Li     {
507*a58d3d2aSXin Li         /* modifies signal in place */
508*a58d3d2aSXin Li         adacomb_process_frame(
509*a58d3d2aSXin Li             &state->cf1_state,
510*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE,
511*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE,
512*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
513*a58d3d2aSXin Li             &hNoLACE->layers.nolace_cf1_kernel,
514*a58d3d2aSXin Li             &hNoLACE->layers.nolace_cf1_gain,
515*a58d3d2aSXin Li             &hNoLACE->layers.nolace_cf1_global_gain,
516*a58d3d2aSXin Li             periods[i_subframe],
517*a58d3d2aSXin Li             NOLACE_COND_DIM,
518*a58d3d2aSXin Li             NOLACE_FRAME_SIZE,
519*a58d3d2aSXin Li             NOLACE_OVERLAP_SIZE,
520*a58d3d2aSXin Li             NOLACE_CF1_KERNEL_SIZE,
521*a58d3d2aSXin Li             NOLACE_CF1_LEFT_PADDING,
522*a58d3d2aSXin Li             NOLACE_CF1_FILTER_GAIN_A,
523*a58d3d2aSXin Li             NOLACE_CF1_FILTER_GAIN_B,
524*a58d3d2aSXin Li             NOLACE_CF1_LOG_GAIN_LIMIT,
525*a58d3d2aSXin Li             hNoLACE->window,
526*a58d3d2aSXin Li             arch);
527*a58d3d2aSXin Li 
528*a58d3d2aSXin Li         compute_generic_conv1d(
529*a58d3d2aSXin Li             &layers->nolace_post_cf1,
530*a58d3d2aSXin Li             feature_transform_buffer + i_subframe * NOLACE_COND_DIM,
531*a58d3d2aSXin Li             state->post_cf1_state,
532*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
533*a58d3d2aSXin Li             NOLACE_COND_DIM,
534*a58d3d2aSXin Li             ACTIVATION_TANH,
535*a58d3d2aSXin Li             arch);
536*a58d3d2aSXin Li     }
537*a58d3d2aSXin Li 
538*a58d3d2aSXin Li     /* update feature buffer */
539*a58d3d2aSXin Li     OPUS_COPY(feature_buffer, feature_transform_buffer, 4 * NOLACE_COND_DIM);
540*a58d3d2aSXin Li 
541*a58d3d2aSXin Li #ifdef DEBUG_NOLACE
542*a58d3d2aSXin Li     fwrite(x_buffer1, sizeof(float), 4 * NOLACE_FRAME_SIZE, f_postcf1);
543*a58d3d2aSXin Li #endif
544*a58d3d2aSXin Li 
545*a58d3d2aSXin Li     /* 2nd comb filtering stage */
546*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
547*a58d3d2aSXin Li     {
548*a58d3d2aSXin Li         /* modifies signal in place */
549*a58d3d2aSXin Li         adacomb_process_frame(
550*a58d3d2aSXin Li             &state->cf2_state,
551*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE,
552*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE,
553*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
554*a58d3d2aSXin Li             &hNoLACE->layers.nolace_cf2_kernel,
555*a58d3d2aSXin Li             &hNoLACE->layers.nolace_cf2_gain,
556*a58d3d2aSXin Li             &hNoLACE->layers.nolace_cf2_global_gain,
557*a58d3d2aSXin Li             periods[i_subframe],
558*a58d3d2aSXin Li             NOLACE_COND_DIM,
559*a58d3d2aSXin Li             NOLACE_FRAME_SIZE,
560*a58d3d2aSXin Li             NOLACE_OVERLAP_SIZE,
561*a58d3d2aSXin Li             NOLACE_CF2_KERNEL_SIZE,
562*a58d3d2aSXin Li             NOLACE_CF2_LEFT_PADDING,
563*a58d3d2aSXin Li             NOLACE_CF2_FILTER_GAIN_A,
564*a58d3d2aSXin Li             NOLACE_CF2_FILTER_GAIN_B,
565*a58d3d2aSXin Li             NOLACE_CF2_LOG_GAIN_LIMIT,
566*a58d3d2aSXin Li             hNoLACE->window,
567*a58d3d2aSXin Li             arch);
568*a58d3d2aSXin Li 
569*a58d3d2aSXin Li         compute_generic_conv1d(
570*a58d3d2aSXin Li             &layers->nolace_post_cf2,
571*a58d3d2aSXin Li             feature_transform_buffer + i_subframe * NOLACE_COND_DIM,
572*a58d3d2aSXin Li             state->post_cf2_state,
573*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
574*a58d3d2aSXin Li             NOLACE_COND_DIM,
575*a58d3d2aSXin Li             ACTIVATION_TANH,
576*a58d3d2aSXin Li             arch);
577*a58d3d2aSXin Li     }
578*a58d3d2aSXin Li 
579*a58d3d2aSXin Li     /* update feature buffer */
580*a58d3d2aSXin Li     OPUS_COPY(feature_buffer, feature_transform_buffer, 4 * NOLACE_COND_DIM);
581*a58d3d2aSXin Li 
582*a58d3d2aSXin Li #ifdef DEBUG_NOLACE
583*a58d3d2aSXin Li     fwrite(x_buffer1, sizeof(float), 4 * NOLACE_FRAME_SIZE, f_postcf2);
584*a58d3d2aSXin Li #endif
585*a58d3d2aSXin Li 
586*a58d3d2aSXin Li     /* final adaptive filtering stage */
587*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
588*a58d3d2aSXin Li     {
589*a58d3d2aSXin Li         adaconv_process_frame(
590*a58d3d2aSXin Li             &state->af1_state,
591*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_FRAME_SIZE * NOLACE_AF1_OUT_CHANNELS,
592*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE,
593*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
594*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af1_kernel,
595*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af1_gain,
596*a58d3d2aSXin Li             NOLACE_COND_DIM,
597*a58d3d2aSXin Li             NOLACE_FRAME_SIZE,
598*a58d3d2aSXin Li             NOLACE_OVERLAP_SIZE,
599*a58d3d2aSXin Li             NOLACE_AF1_IN_CHANNELS,
600*a58d3d2aSXin Li             NOLACE_AF1_OUT_CHANNELS,
601*a58d3d2aSXin Li             NOLACE_AF1_KERNEL_SIZE,
602*a58d3d2aSXin Li             NOLACE_AF1_LEFT_PADDING,
603*a58d3d2aSXin Li             NOLACE_AF1_FILTER_GAIN_A,
604*a58d3d2aSXin Li             NOLACE_AF1_FILTER_GAIN_B,
605*a58d3d2aSXin Li             NOLACE_AF1_SHAPE_GAIN,
606*a58d3d2aSXin Li             hNoLACE->window,
607*a58d3d2aSXin Li             arch);
608*a58d3d2aSXin Li 
609*a58d3d2aSXin Li         compute_generic_conv1d(
610*a58d3d2aSXin Li             &layers->nolace_post_af1,
611*a58d3d2aSXin Li             feature_transform_buffer + i_subframe * NOLACE_COND_DIM,
612*a58d3d2aSXin Li             state->post_af1_state,
613*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
614*a58d3d2aSXin Li             NOLACE_COND_DIM,
615*a58d3d2aSXin Li             ACTIVATION_TANH,
616*a58d3d2aSXin Li             arch);
617*a58d3d2aSXin Li     }
618*a58d3d2aSXin Li 
619*a58d3d2aSXin Li     /* update feature buffer */
620*a58d3d2aSXin Li     OPUS_COPY(feature_buffer, feature_transform_buffer, 4 * NOLACE_COND_DIM);
621*a58d3d2aSXin Li 
622*a58d3d2aSXin Li #ifdef DEBUG_NOLACE
623*a58d3d2aSXin Li     fwrite(x_buffer2, sizeof(float), 4 * NOLACE_FRAME_SIZE * NOLACE_AF1_OUT_CHANNELS, f_postaf1);
624*a58d3d2aSXin Li #endif
625*a58d3d2aSXin Li 
626*a58d3d2aSXin Li     /* first shape-mix round */
627*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
628*a58d3d2aSXin Li     {
629*a58d3d2aSXin Li         celt_assert(NOLACE_AF1_OUT_CHANNELS == 2);
630*a58d3d2aSXin Li         /* modifies second channel in place */
631*a58d3d2aSXin Li         adashape_process_frame(
632*a58d3d2aSXin Li             &state->tdshape1_state,
633*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_AF1_OUT_CHANNELS * NOLACE_FRAME_SIZE + NOLACE_FRAME_SIZE,
634*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_AF1_OUT_CHANNELS * NOLACE_FRAME_SIZE + NOLACE_FRAME_SIZE,
635*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
636*a58d3d2aSXin Li             &layers->nolace_tdshape1_alpha1_f,
637*a58d3d2aSXin Li             &layers->nolace_tdshape1_alpha1_t,
638*a58d3d2aSXin Li             &layers->nolace_tdshape1_alpha2,
639*a58d3d2aSXin Li             NOLACE_TDSHAPE1_FEATURE_DIM,
640*a58d3d2aSXin Li             NOLACE_TDSHAPE1_FRAME_SIZE,
641*a58d3d2aSXin Li             NOLACE_TDSHAPE1_AVG_POOL_K,
642*a58d3d2aSXin Li             arch
643*a58d3d2aSXin Li         );
644*a58d3d2aSXin Li 
645*a58d3d2aSXin Li         adaconv_process_frame(
646*a58d3d2aSXin Li             &state->af2_state,
647*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE * NOLACE_AF2_OUT_CHANNELS,
648*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_FRAME_SIZE * NOLACE_AF2_IN_CHANNELS,
649*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
650*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af2_kernel,
651*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af2_gain,
652*a58d3d2aSXin Li             NOLACE_COND_DIM,
653*a58d3d2aSXin Li             NOLACE_FRAME_SIZE,
654*a58d3d2aSXin Li             NOLACE_OVERLAP_SIZE,
655*a58d3d2aSXin Li             NOLACE_AF2_IN_CHANNELS,
656*a58d3d2aSXin Li             NOLACE_AF2_OUT_CHANNELS,
657*a58d3d2aSXin Li             NOLACE_AF2_KERNEL_SIZE,
658*a58d3d2aSXin Li             NOLACE_AF2_LEFT_PADDING,
659*a58d3d2aSXin Li             NOLACE_AF2_FILTER_GAIN_A,
660*a58d3d2aSXin Li             NOLACE_AF2_FILTER_GAIN_B,
661*a58d3d2aSXin Li             NOLACE_AF2_SHAPE_GAIN,
662*a58d3d2aSXin Li             hNoLACE->window,
663*a58d3d2aSXin Li             arch);
664*a58d3d2aSXin Li 
665*a58d3d2aSXin Li         compute_generic_conv1d(
666*a58d3d2aSXin Li             &layers->nolace_post_af2,
667*a58d3d2aSXin Li             feature_transform_buffer + i_subframe * NOLACE_COND_DIM,
668*a58d3d2aSXin Li             state->post_af2_state,
669*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
670*a58d3d2aSXin Li             NOLACE_COND_DIM,
671*a58d3d2aSXin Li             ACTIVATION_TANH,
672*a58d3d2aSXin Li             arch);
673*a58d3d2aSXin Li     }
674*a58d3d2aSXin Li 
675*a58d3d2aSXin Li     /* update feature buffer */
676*a58d3d2aSXin Li     OPUS_COPY(feature_buffer, feature_transform_buffer, 4 * NOLACE_COND_DIM);
677*a58d3d2aSXin Li 
678*a58d3d2aSXin Li #ifdef DEBUG_NOLACE
679*a58d3d2aSXin Li     fwrite(x_buffer1, sizeof(float), 4 * NOLACE_FRAME_SIZE * NOLACE_AF2_OUT_CHANNELS, f_postaf2);
680*a58d3d2aSXin Li #endif
681*a58d3d2aSXin Li 
682*a58d3d2aSXin Li     /* second shape-mix round */
683*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
684*a58d3d2aSXin Li     {
685*a58d3d2aSXin Li         celt_assert(NOLACE_AF2_OUT_CHANNELS == 2);
686*a58d3d2aSXin Li         /* modifies second channel in place */
687*a58d3d2aSXin Li         adashape_process_frame(
688*a58d3d2aSXin Li             &state->tdshape2_state,
689*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_AF2_OUT_CHANNELS * NOLACE_FRAME_SIZE + NOLACE_FRAME_SIZE,
690*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_AF2_OUT_CHANNELS * NOLACE_FRAME_SIZE + NOLACE_FRAME_SIZE,
691*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
692*a58d3d2aSXin Li             &layers->nolace_tdshape2_alpha1_f,
693*a58d3d2aSXin Li             &layers->nolace_tdshape2_alpha1_t,
694*a58d3d2aSXin Li             &layers->nolace_tdshape2_alpha2,
695*a58d3d2aSXin Li             NOLACE_TDSHAPE2_FEATURE_DIM,
696*a58d3d2aSXin Li             NOLACE_TDSHAPE2_FRAME_SIZE,
697*a58d3d2aSXin Li             NOLACE_TDSHAPE2_AVG_POOL_K,
698*a58d3d2aSXin Li             arch
699*a58d3d2aSXin Li         );
700*a58d3d2aSXin Li 
701*a58d3d2aSXin Li         adaconv_process_frame(
702*a58d3d2aSXin Li             &state->af3_state,
703*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_FRAME_SIZE * NOLACE_AF3_OUT_CHANNELS,
704*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE * NOLACE_AF3_IN_CHANNELS,
705*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
706*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af3_kernel,
707*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af3_gain,
708*a58d3d2aSXin Li             NOLACE_COND_DIM,
709*a58d3d2aSXin Li             NOLACE_FRAME_SIZE,
710*a58d3d2aSXin Li             NOLACE_OVERLAP_SIZE,
711*a58d3d2aSXin Li             NOLACE_AF3_IN_CHANNELS,
712*a58d3d2aSXin Li             NOLACE_AF3_OUT_CHANNELS,
713*a58d3d2aSXin Li             NOLACE_AF3_KERNEL_SIZE,
714*a58d3d2aSXin Li             NOLACE_AF3_LEFT_PADDING,
715*a58d3d2aSXin Li             NOLACE_AF3_FILTER_GAIN_A,
716*a58d3d2aSXin Li             NOLACE_AF3_FILTER_GAIN_B,
717*a58d3d2aSXin Li             NOLACE_AF3_SHAPE_GAIN,
718*a58d3d2aSXin Li             hNoLACE->window,
719*a58d3d2aSXin Li             arch);
720*a58d3d2aSXin Li 
721*a58d3d2aSXin Li         compute_generic_conv1d(
722*a58d3d2aSXin Li             &layers->nolace_post_af3,
723*a58d3d2aSXin Li             feature_transform_buffer + i_subframe * NOLACE_COND_DIM,
724*a58d3d2aSXin Li             state->post_af3_state,
725*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
726*a58d3d2aSXin Li             NOLACE_COND_DIM,
727*a58d3d2aSXin Li             ACTIVATION_TANH,
728*a58d3d2aSXin Li             arch);
729*a58d3d2aSXin Li     }
730*a58d3d2aSXin Li 
731*a58d3d2aSXin Li     /* update feature buffer */
732*a58d3d2aSXin Li     OPUS_COPY(feature_buffer, feature_transform_buffer, 4 * NOLACE_COND_DIM);
733*a58d3d2aSXin Li 
734*a58d3d2aSXin Li     /* third shape-mix round */
735*a58d3d2aSXin Li     for (i_subframe = 0; i_subframe < 4; i_subframe++)
736*a58d3d2aSXin Li     {
737*a58d3d2aSXin Li         celt_assert(NOLACE_AF3_OUT_CHANNELS == 2);
738*a58d3d2aSXin Li         /* modifies second channel in place */
739*a58d3d2aSXin Li         adashape_process_frame(
740*a58d3d2aSXin Li             &state->tdshape3_state,
741*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_AF3_OUT_CHANNELS * NOLACE_FRAME_SIZE + NOLACE_FRAME_SIZE,
742*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_AF3_OUT_CHANNELS * NOLACE_FRAME_SIZE + NOLACE_FRAME_SIZE,
743*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
744*a58d3d2aSXin Li             &layers->nolace_tdshape3_alpha1_f,
745*a58d3d2aSXin Li             &layers->nolace_tdshape3_alpha1_t,
746*a58d3d2aSXin Li             &layers->nolace_tdshape3_alpha2,
747*a58d3d2aSXin Li             NOLACE_TDSHAPE3_FEATURE_DIM,
748*a58d3d2aSXin Li             NOLACE_TDSHAPE3_FRAME_SIZE,
749*a58d3d2aSXin Li             NOLACE_TDSHAPE3_AVG_POOL_K,
750*a58d3d2aSXin Li             arch
751*a58d3d2aSXin Li         );
752*a58d3d2aSXin Li 
753*a58d3d2aSXin Li         adaconv_process_frame(
754*a58d3d2aSXin Li             &state->af4_state,
755*a58d3d2aSXin Li             x_buffer1 + i_subframe * NOLACE_FRAME_SIZE * NOLACE_AF4_OUT_CHANNELS,
756*a58d3d2aSXin Li             x_buffer2 + i_subframe * NOLACE_FRAME_SIZE * NOLACE_AF4_IN_CHANNELS,
757*a58d3d2aSXin Li             feature_buffer + i_subframe * NOLACE_COND_DIM,
758*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af4_kernel,
759*a58d3d2aSXin Li             &hNoLACE->layers.nolace_af4_gain,
760*a58d3d2aSXin Li             NOLACE_COND_DIM,
761*a58d3d2aSXin Li             NOLACE_FRAME_SIZE,
762*a58d3d2aSXin Li             NOLACE_OVERLAP_SIZE,
763*a58d3d2aSXin Li             NOLACE_AF4_IN_CHANNELS,
764*a58d3d2aSXin Li             NOLACE_AF4_OUT_CHANNELS,
765*a58d3d2aSXin Li             NOLACE_AF4_KERNEL_SIZE,
766*a58d3d2aSXin Li             NOLACE_AF4_LEFT_PADDING,
767*a58d3d2aSXin Li             NOLACE_AF4_FILTER_GAIN_A,
768*a58d3d2aSXin Li             NOLACE_AF4_FILTER_GAIN_B,
769*a58d3d2aSXin Li             NOLACE_AF4_SHAPE_GAIN,
770*a58d3d2aSXin Li             hNoLACE->window,
771*a58d3d2aSXin Li             arch);
772*a58d3d2aSXin Li 
773*a58d3d2aSXin Li     }
774*a58d3d2aSXin Li 
775*a58d3d2aSXin Li 
776*a58d3d2aSXin Li     /* de-emphasis */
777*a58d3d2aSXin Li     for (i_sample = 0; i_sample < 4 * NOLACE_FRAME_SIZE; i_sample ++)
778*a58d3d2aSXin Li     {
779*a58d3d2aSXin Li         x_out[i_sample] = x_buffer1[i_sample] + NOLACE_PREEMPH * state->deemph_mem;
780*a58d3d2aSXin Li         state->deemph_mem = x_out[i_sample];
781*a58d3d2aSXin Li     }
782*a58d3d2aSXin Li #ifdef DEBUG_NOLACE
783*a58d3d2aSXin Li     fwrite(x_out, sizeof(float), 4 * NOLACE_FRAME_SIZE, f_xdeemph);
784*a58d3d2aSXin Li #endif
785*a58d3d2aSXin Li }
786*a58d3d2aSXin Li 
787*a58d3d2aSXin Li #endif /* #ifndef DISABLE_NOLACE */
788*a58d3d2aSXin Li 
789*a58d3d2aSXin Li /* API */
790*a58d3d2aSXin Li 
osce_reset(silk_OSCE_struct * hOSCE,int method)791*a58d3d2aSXin Li void osce_reset(silk_OSCE_struct *hOSCE, int method)
792*a58d3d2aSXin Li {
793*a58d3d2aSXin Li     OSCEState *state = &hOSCE->state;
794*a58d3d2aSXin Li 
795*a58d3d2aSXin Li     OPUS_CLEAR(&hOSCE->features, 1);
796*a58d3d2aSXin Li 
797*a58d3d2aSXin Li     switch(method)
798*a58d3d2aSXin Li     {
799*a58d3d2aSXin Li         case OSCE_METHOD_NONE:
800*a58d3d2aSXin Li             break;
801*a58d3d2aSXin Li #ifndef DISABLE_LACE
802*a58d3d2aSXin Li         case OSCE_METHOD_LACE:
803*a58d3d2aSXin Li             reset_lace_state(&state->lace);
804*a58d3d2aSXin Li             break;
805*a58d3d2aSXin Li #endif
806*a58d3d2aSXin Li #ifndef DISABLE_NOLACE
807*a58d3d2aSXin Li         case OSCE_METHOD_NOLACE:
808*a58d3d2aSXin Li             reset_nolace_state(&state->nolace);
809*a58d3d2aSXin Li             break;
810*a58d3d2aSXin Li #endif
811*a58d3d2aSXin Li         default:
812*a58d3d2aSXin Li             celt_assert(0 && "method not defined"); /* Question: return error code? */
813*a58d3d2aSXin Li     }
814*a58d3d2aSXin Li     hOSCE->method = method;
815*a58d3d2aSXin Li     hOSCE->features.reset = 2;
816*a58d3d2aSXin Li }
817*a58d3d2aSXin Li 
818*a58d3d2aSXin Li 
819*a58d3d2aSXin Li #if 0
820*a58d3d2aSXin Li #include <stdio.h>
821*a58d3d2aSXin Li static void print_float_array(FILE *fid, const char  *name, const float *array, int n)
822*a58d3d2aSXin Li {
823*a58d3d2aSXin Li     int i;
824*a58d3d2aSXin Li     for (i = 0; i < n; i++)
825*a58d3d2aSXin Li     {
826*a58d3d2aSXin Li         fprintf(fid, "%s[%d]: %f\n", name, i, array[i]);
827*a58d3d2aSXin Li     }
828*a58d3d2aSXin Li }
829*a58d3d2aSXin Li 
830*a58d3d2aSXin Li static void print_int_array(FILE *fid, const char  *name, const int *array, int n)
831*a58d3d2aSXin Li {
832*a58d3d2aSXin Li     int i;
833*a58d3d2aSXin Li     for (i = 0; i < n; i++)
834*a58d3d2aSXin Li     {
835*a58d3d2aSXin Li         fprintf(fid, "%s[%d]: %d\n", name, i, array[i]);
836*a58d3d2aSXin Li     }
837*a58d3d2aSXin Li }
838*a58d3d2aSXin Li 
839*a58d3d2aSXin Li static void print_int8_array(FILE *fid, const char  *name, const opus_int8 *array, int n)
840*a58d3d2aSXin Li {
841*a58d3d2aSXin Li     int i;
842*a58d3d2aSXin Li     for (i = 0; i < n; i++)
843*a58d3d2aSXin Li     {
844*a58d3d2aSXin Li         fprintf(fid, "%s[%d]: %d\n", name, i, array[i]);
845*a58d3d2aSXin Li     }
846*a58d3d2aSXin Li }
847*a58d3d2aSXin Li 
848*a58d3d2aSXin Li static void print_linear_layer(FILE *fid, const char *name, LinearLayer *layer)
849*a58d3d2aSXin Li {
850*a58d3d2aSXin Li     int i, n_in, n_out, n_total;
851*a58d3d2aSXin Li     char tmp[256];
852*a58d3d2aSXin Li 
853*a58d3d2aSXin Li     n_in = layer->nb_inputs;
854*a58d3d2aSXin Li     n_out = layer->nb_outputs;
855*a58d3d2aSXin Li     n_total = n_in * n_out;
856*a58d3d2aSXin Li 
857*a58d3d2aSXin Li     fprintf(fid, "\nprinting layer %s...\n", name);
858*a58d3d2aSXin Li     fprintf(fid, "%s.nb_inputs: %d\n%s.nb_outputs: %d\n", name, n_in, name, n_out);
859*a58d3d2aSXin Li 
860*a58d3d2aSXin Li     if (layer->bias !=NULL){}
861*a58d3d2aSXin Li     if (layer->subias !=NULL){}
862*a58d3d2aSXin Li     if (layer->weights !=NULL){}
863*a58d3d2aSXin Li     if (layer->float_weights !=NULL){}
864*a58d3d2aSXin Li 
865*a58d3d2aSXin Li     if (layer->bias != NULL) {sprintf(tmp, "%s.bias", name); print_float_array(fid, tmp, layer->bias, n_out);}
866*a58d3d2aSXin Li     if (layer->subias != NULL) {sprintf(tmp, "%s.subias", name); print_float_array(fid, tmp, layer->subias, n_out);}
867*a58d3d2aSXin Li     if (layer->weights != NULL) {sprintf(tmp, "%s.weights", name); print_int8_array(fid, tmp, layer->weights, n_total);}
868*a58d3d2aSXin Li     if (layer->float_weights != NULL) {sprintf(tmp, "%s.float_weights", name); print_float_array(fid, tmp, layer->float_weights, n_total);}
869*a58d3d2aSXin Li     //if (layer->weights_idx != NULL) {sprintf(tmp, "%s.weights_idx", name); print_float_array(fid, tmp, layer->weights_idx, n_total);}
870*a58d3d2aSXin Li     if (layer->diag != NULL) {sprintf(tmp, "%s.diag", name); print_float_array(fid, tmp, layer->diag, n_in);}
871*a58d3d2aSXin Li     if (layer->scale != NULL) {sprintf(tmp, "%s.scale", name); print_float_array(fid, tmp, layer->scale, n_out);}
872*a58d3d2aSXin Li 
873*a58d3d2aSXin Li }
874*a58d3d2aSXin Li #endif
875*a58d3d2aSXin Li 
osce_load_models(OSCEModel * model,const void * data,int len)876*a58d3d2aSXin Li int osce_load_models(OSCEModel *model, const void *data, int len)
877*a58d3d2aSXin Li {
878*a58d3d2aSXin Li     int ret = 0;
879*a58d3d2aSXin Li     WeightArray *list;
880*a58d3d2aSXin Li 
881*a58d3d2aSXin Li     if (data != NULL  && len)
882*a58d3d2aSXin Li     {
883*a58d3d2aSXin Li         /* init from buffer */
884*a58d3d2aSXin Li         parse_weights(&list, data, len);
885*a58d3d2aSXin Li 
886*a58d3d2aSXin Li #ifndef DISABLE_LACE
887*a58d3d2aSXin Li         if (ret == 0) {ret = init_lace(&model->lace, list);}
888*a58d3d2aSXin Li #endif
889*a58d3d2aSXin Li 
890*a58d3d2aSXin Li #ifndef DISABLE_NOLACE
891*a58d3d2aSXin Li         if (ret == 0) {ret = init_nolace(&model->nolace, list);}
892*a58d3d2aSXin Li #endif
893*a58d3d2aSXin Li 
894*a58d3d2aSXin Li         free(list);
895*a58d3d2aSXin Li     } else
896*a58d3d2aSXin Li     {
897*a58d3d2aSXin Li #ifdef USE_WEIGHTS_FILE
898*a58d3d2aSXin Li         return -1;
899*a58d3d2aSXin Li #else
900*a58d3d2aSXin Li #ifndef DISABLE_LACE
901*a58d3d2aSXin Li         if (ret == 0) {ret = init_lace(&model->lace, lacelayers_arrays);}
902*a58d3d2aSXin Li #endif
903*a58d3d2aSXin Li 
904*a58d3d2aSXin Li #ifndef DISABLE_NOLACE
905*a58d3d2aSXin Li         if (ret == 0) {ret = init_nolace(&model->nolace, nolacelayers_arrays);}
906*a58d3d2aSXin Li #endif
907*a58d3d2aSXin Li 
908*a58d3d2aSXin Li #endif /* USE_WEIGHTS_FILE */
909*a58d3d2aSXin Li     }
910*a58d3d2aSXin Li 
911*a58d3d2aSXin Li     ret = ret ? -1 : 0;
912*a58d3d2aSXin Li     return ret;
913*a58d3d2aSXin Li }
914*a58d3d2aSXin Li 
osce_enhance_frame(OSCEModel * model,silk_decoder_state * psDec,silk_decoder_control * psDecCtrl,opus_int16 xq[],opus_int32 num_bits,int arch)915*a58d3d2aSXin Li void osce_enhance_frame(
916*a58d3d2aSXin Li     OSCEModel                   *model,                         /* I    OSCE model struct                           */
917*a58d3d2aSXin Li     silk_decoder_state          *psDec,                         /* I/O  Decoder state                               */
918*a58d3d2aSXin Li     silk_decoder_control        *psDecCtrl,                     /* I    Decoder control                             */
919*a58d3d2aSXin Li     opus_int16                  xq[],                           /* I/O  Decoded speech                              */
920*a58d3d2aSXin Li     opus_int32                  num_bits,                       /* I    Size of SILK payload in bits                */
921*a58d3d2aSXin Li     int                         arch                            /* I    Run-time architecture                       */
922*a58d3d2aSXin Li )
923*a58d3d2aSXin Li {
924*a58d3d2aSXin Li     float in_buffer[320];
925*a58d3d2aSXin Li     float out_buffer[320];
926*a58d3d2aSXin Li     float features[4 * OSCE_FEATURE_DIM];
927*a58d3d2aSXin Li     float numbits[2];
928*a58d3d2aSXin Li     int periods[4];
929*a58d3d2aSXin Li     int i;
930*a58d3d2aSXin Li     int method;
931*a58d3d2aSXin Li 
932*a58d3d2aSXin Li     /* enhancement only implemented for 20 ms frame at 16kHz */
933*a58d3d2aSXin Li     if (psDec->fs_kHz != 16 || psDec->nb_subfr != 4)
934*a58d3d2aSXin Li     {
935*a58d3d2aSXin Li         osce_reset(&psDec->osce, psDec->osce.method);
936*a58d3d2aSXin Li         return;
937*a58d3d2aSXin Li     }
938*a58d3d2aSXin Li 
939*a58d3d2aSXin Li     osce_calculate_features(psDec, psDecCtrl, features, numbits, periods, xq, num_bits);
940*a58d3d2aSXin Li 
941*a58d3d2aSXin Li     /* scale input */
942*a58d3d2aSXin Li     for (i = 0; i < 320; i++)
943*a58d3d2aSXin Li     {
944*a58d3d2aSXin Li         in_buffer[i] = ((float) xq[i]) * (1.f/32768.f);
945*a58d3d2aSXin Li     }
946*a58d3d2aSXin Li 
947*a58d3d2aSXin Li     if (model->loaded)
948*a58d3d2aSXin Li         method = psDec->osce.method;
949*a58d3d2aSXin Li     else
950*a58d3d2aSXin Li         method = OSCE_METHOD_NONE;
951*a58d3d2aSXin Li     switch(method)
952*a58d3d2aSXin Li     {
953*a58d3d2aSXin Li         case OSCE_METHOD_NONE:
954*a58d3d2aSXin Li             OPUS_COPY(out_buffer, in_buffer, 320);
955*a58d3d2aSXin Li             break;
956*a58d3d2aSXin Li #ifndef DISABLE_LACE
957*a58d3d2aSXin Li         case OSCE_METHOD_LACE:
958*a58d3d2aSXin Li             lace_process_20ms_frame(&model->lace, &psDec->osce.state.lace, out_buffer, in_buffer, features, numbits, periods, arch);
959*a58d3d2aSXin Li             break;
960*a58d3d2aSXin Li #endif
961*a58d3d2aSXin Li #ifndef DISABLE_NOLACE
962*a58d3d2aSXin Li         case OSCE_METHOD_NOLACE:
963*a58d3d2aSXin Li             nolace_process_20ms_frame(&model->nolace, &psDec->osce.state.nolace, out_buffer, in_buffer, features, numbits, periods, arch);
964*a58d3d2aSXin Li             break;
965*a58d3d2aSXin Li #endif
966*a58d3d2aSXin Li         default:
967*a58d3d2aSXin Li             celt_assert(0 && "method not defined");
968*a58d3d2aSXin Li     }
969*a58d3d2aSXin Li 
970*a58d3d2aSXin Li #ifdef ENABLE_OSCE_TRAINING_DATA
971*a58d3d2aSXin Li     int  k;
972*a58d3d2aSXin Li 
973*a58d3d2aSXin Li     static FILE *flpc = NULL;
974*a58d3d2aSXin Li     static FILE *fgain = NULL;
975*a58d3d2aSXin Li     static FILE *fltp = NULL;
976*a58d3d2aSXin Li     static FILE *fperiod = NULL;
977*a58d3d2aSXin Li     static FILE *fnoisy16k = NULL;
978*a58d3d2aSXin Li     static FILE* f_numbits = NULL;
979*a58d3d2aSXin Li     static FILE* f_numbits_smooth = NULL;
980*a58d3d2aSXin Li 
981*a58d3d2aSXin Li     if (flpc == NULL) {flpc = fopen("features_lpc.f32", "wb");}
982*a58d3d2aSXin Li     if (fgain == NULL) {fgain = fopen("features_gain.f32", "wb");}
983*a58d3d2aSXin Li     if (fltp == NULL) {fltp = fopen("features_ltp.f32", "wb");}
984*a58d3d2aSXin Li     if (fperiod == NULL) {fperiod = fopen("features_period.s16", "wb");}
985*a58d3d2aSXin Li     if (fnoisy16k == NULL) {fnoisy16k = fopen("noisy_16k.s16", "wb");}
986*a58d3d2aSXin Li     if(f_numbits == NULL) {f_numbits = fopen("features_num_bits.s32", "wb");}
987*a58d3d2aSXin Li     if (f_numbits_smooth == NULL) {f_numbits_smooth = fopen("features_num_bits_smooth.f32", "wb");}
988*a58d3d2aSXin Li 
989*a58d3d2aSXin Li     fwrite(&num_bits, sizeof(num_bits), 1, f_numbits);
990*a58d3d2aSXin Li     fwrite(&(psDec->osce.features.numbits_smooth), sizeof(psDec->osce.features.numbits_smooth), 1, f_numbits_smooth);
991*a58d3d2aSXin Li 
992*a58d3d2aSXin Li     for (k = 0; k < psDec->nb_subfr; k++)
993*a58d3d2aSXin Li     {
994*a58d3d2aSXin Li         float tmp;
995*a58d3d2aSXin Li         int16_t itmp;
996*a58d3d2aSXin Li         float lpc_buffer[16] = {0};
997*a58d3d2aSXin Li         opus_int16 *A_Q12, *B_Q14;
998*a58d3d2aSXin Li 
999*a58d3d2aSXin Li         (void) num_bits;
1000*a58d3d2aSXin Li         (void) arch;
1001*a58d3d2aSXin Li 
1002*a58d3d2aSXin Li         /* gain */
1003*a58d3d2aSXin Li         tmp = (float) psDecCtrl->Gains_Q16[k] / (1UL << 16);
1004*a58d3d2aSXin Li         fwrite(&tmp, sizeof(tmp), 1, fgain);
1005*a58d3d2aSXin Li 
1006*a58d3d2aSXin Li         /* LPC */
1007*a58d3d2aSXin Li         A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
1008*a58d3d2aSXin Li         for (i = 0; i < psDec->LPC_order; i++)
1009*a58d3d2aSXin Li         {
1010*a58d3d2aSXin Li             lpc_buffer[i] = (float) A_Q12[i] / (1U << 12);
1011*a58d3d2aSXin Li         }
1012*a58d3d2aSXin Li         fwrite(lpc_buffer, sizeof(lpc_buffer[0]), 16, flpc);
1013*a58d3d2aSXin Li 
1014*a58d3d2aSXin Li         /* LTP */
1015*a58d3d2aSXin Li         B_Q14 = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
1016*a58d3d2aSXin Li         for (i = 0; i < 5; i++)
1017*a58d3d2aSXin Li         {
1018*a58d3d2aSXin Li             tmp = (float) B_Q14[i] / (1U << 14);
1019*a58d3d2aSXin Li             fwrite(&tmp, sizeof(tmp), 1, fltp);
1020*a58d3d2aSXin Li         }
1021*a58d3d2aSXin Li 
1022*a58d3d2aSXin Li         /* periods */
1023*a58d3d2aSXin Li         itmp = psDec->indices.signalType == TYPE_VOICED ? psDecCtrl->pitchL[ k ] : 0;
1024*a58d3d2aSXin Li         fwrite(&itmp, sizeof(itmp), 1, fperiod);
1025*a58d3d2aSXin Li     }
1026*a58d3d2aSXin Li 
1027*a58d3d2aSXin Li     fwrite(xq, psDec->nb_subfr * psDec->subfr_length, sizeof(xq[0]), fnoisy16k);
1028*a58d3d2aSXin Li #endif
1029*a58d3d2aSXin Li 
1030*a58d3d2aSXin Li     if (psDec->osce.features.reset > 1)
1031*a58d3d2aSXin Li     {
1032*a58d3d2aSXin Li         OPUS_COPY(out_buffer, in_buffer, 320);
1033*a58d3d2aSXin Li         psDec->osce.features.reset --;
1034*a58d3d2aSXin Li     }
1035*a58d3d2aSXin Li     else if (psDec->osce.features.reset)
1036*a58d3d2aSXin Li     {
1037*a58d3d2aSXin Li         osce_cross_fade_10ms(out_buffer, in_buffer, 320);
1038*a58d3d2aSXin Li         psDec->osce.features.reset = 0;
1039*a58d3d2aSXin Li     }
1040*a58d3d2aSXin Li 
1041*a58d3d2aSXin Li     /* scale output */
1042*a58d3d2aSXin Li     for (i = 0; i < 320; i++)
1043*a58d3d2aSXin Li     {
1044*a58d3d2aSXin Li         float tmp = 32768.f * out_buffer[i];
1045*a58d3d2aSXin Li         if (tmp > 32767.f) tmp = 32767.f;
1046*a58d3d2aSXin Li         if (tmp < -32767.f) tmp = -32767.f;
1047*a58d3d2aSXin Li         xq[i] = float2int(tmp);
1048*a58d3d2aSXin Li     }
1049*a58d3d2aSXin Li 
1050*a58d3d2aSXin Li }
1051*a58d3d2aSXin Li 
1052*a58d3d2aSXin Li 
1053*a58d3d2aSXin Li #if 0
1054*a58d3d2aSXin Li 
1055*a58d3d2aSXin Li #include <stdio.h>
1056*a58d3d2aSXin Li 
1057*a58d3d2aSXin Li void lace_feature_net_compare(
1058*a58d3d2aSXin Li     const char * prefix,
1059*a58d3d2aSXin Li     int num_frames,
1060*a58d3d2aSXin Li     LACE* hLACE
1061*a58d3d2aSXin Li )
1062*a58d3d2aSXin Li {
1063*a58d3d2aSXin Li     char in_feature_file[256];
1064*a58d3d2aSXin Li     char out_feature_file[256];
1065*a58d3d2aSXin Li     char numbits_file[256];
1066*a58d3d2aSXin Li     char periods_file[256];
1067*a58d3d2aSXin Li     char message[512];
1068*a58d3d2aSXin Li     int i_frame, i_feature;
1069*a58d3d2aSXin Li     float mse;
1070*a58d3d2aSXin Li     float in_features[4 * LACE_NUM_FEATURES];
1071*a58d3d2aSXin Li     float out_features[4 * LACE_COND_DIM];
1072*a58d3d2aSXin Li     float out_features2[4 * LACE_COND_DIM];
1073*a58d3d2aSXin Li     float numbits[2];
1074*a58d3d2aSXin Li     int periods[4];
1075*a58d3d2aSXin Li 
1076*a58d3d2aSXin Li     init_lace(hLACE);
1077*a58d3d2aSXin Li 
1078*a58d3d2aSXin Li     FILE *f_in_features, *f_out_features, *f_numbits, *f_periods;
1079*a58d3d2aSXin Li 
1080*a58d3d2aSXin Li     strcpy(in_feature_file, prefix);
1081*a58d3d2aSXin Li     strcat(in_feature_file, "_in_features.f32");
1082*a58d3d2aSXin Li     f_in_features = fopen(in_feature_file, "rb");
1083*a58d3d2aSXin Li     if (f_in_features == NULL)
1084*a58d3d2aSXin Li     {
1085*a58d3d2aSXin Li         sprintf(message, "could not open file %s", in_feature_file);
1086*a58d3d2aSXin Li         perror(message);
1087*a58d3d2aSXin Li         exit(1);
1088*a58d3d2aSXin Li     }
1089*a58d3d2aSXin Li 
1090*a58d3d2aSXin Li     strcpy(out_feature_file, prefix);
1091*a58d3d2aSXin Li     strcat(out_feature_file, "_out_features.f32");
1092*a58d3d2aSXin Li     f_out_features = fopen(out_feature_file, "rb");
1093*a58d3d2aSXin Li     if (f_out_features == NULL)
1094*a58d3d2aSXin Li     {
1095*a58d3d2aSXin Li         sprintf(message, "could not open file %s", out_feature_file);
1096*a58d3d2aSXin Li         perror(message);
1097*a58d3d2aSXin Li         exit(1);
1098*a58d3d2aSXin Li     }
1099*a58d3d2aSXin Li 
1100*a58d3d2aSXin Li     strcpy(periods_file, prefix);
1101*a58d3d2aSXin Li     strcat(periods_file, "_periods.s32");
1102*a58d3d2aSXin Li     f_periods = fopen(periods_file, "rb");
1103*a58d3d2aSXin Li     if (f_periods == NULL)
1104*a58d3d2aSXin Li     {
1105*a58d3d2aSXin Li         sprintf(message, "could not open file %s", periods_file);
1106*a58d3d2aSXin Li         perror(message);
1107*a58d3d2aSXin Li         exit(1);
1108*a58d3d2aSXin Li     }
1109*a58d3d2aSXin Li 
1110*a58d3d2aSXin Li     strcpy(numbits_file, prefix);
1111*a58d3d2aSXin Li     strcat(numbits_file, "_numbits.f32");
1112*a58d3d2aSXin Li     f_numbits = fopen(numbits_file, "rb");
1113*a58d3d2aSXin Li     if (f_numbits == NULL)
1114*a58d3d2aSXin Li     {
1115*a58d3d2aSXin Li         sprintf(message, "could not open file %s", numbits_file);
1116*a58d3d2aSXin Li         perror(message);
1117*a58d3d2aSXin Li         exit(1);
1118*a58d3d2aSXin Li     }
1119*a58d3d2aSXin Li 
1120*a58d3d2aSXin Li     for (i_frame = 0; i_frame < num_frames; i_frame ++)
1121*a58d3d2aSXin Li     {
1122*a58d3d2aSXin Li         if(fread(in_features, sizeof(float), 4 * LACE_NUM_FEATURES, f_in_features) != 4 * LACE_NUM_FEATURES)
1123*a58d3d2aSXin Li         {
1124*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from in_features\n", i_frame);
1125*a58d3d2aSXin Li             exit(1);
1126*a58d3d2aSXin Li         }
1127*a58d3d2aSXin Li         if(fread(out_features, sizeof(float), 4 * LACE_COND_DIM, f_out_features) != 4 * LACE_COND_DIM)
1128*a58d3d2aSXin Li         {
1129*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from out_features\n", i_frame);
1130*a58d3d2aSXin Li             exit(1);
1131*a58d3d2aSXin Li         }
1132*a58d3d2aSXin Li         if(fread(periods, sizeof(int), 4, f_periods) != 4)
1133*a58d3d2aSXin Li         {
1134*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from periods\n", i_frame);
1135*a58d3d2aSXin Li             exit(1);
1136*a58d3d2aSXin Li         }
1137*a58d3d2aSXin Li         if(fread(numbits, sizeof(float), 2, f_numbits) != 2)
1138*a58d3d2aSXin Li         {
1139*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from numbits\n", i_frame);
1140*a58d3d2aSXin Li             exit(1);
1141*a58d3d2aSXin Li         }
1142*a58d3d2aSXin Li 
1143*a58d3d2aSXin Li 
1144*a58d3d2aSXin Li         lace_feature_net(hLACE, out_features2, in_features, numbits, periods);
1145*a58d3d2aSXin Li 
1146*a58d3d2aSXin Li         float mse = 0;
1147*a58d3d2aSXin Li         for (int i = 0; i < 4 * LACE_COND_DIM; i ++)
1148*a58d3d2aSXin Li         {
1149*a58d3d2aSXin Li             mse += pow(out_features[i] - out_features2[i], 2);
1150*a58d3d2aSXin Li         }
1151*a58d3d2aSXin Li         mse /= (4 * LACE_COND_DIM);
1152*a58d3d2aSXin Li         printf("rmse: %f\n", sqrt(mse));
1153*a58d3d2aSXin Li 
1154*a58d3d2aSXin Li     }
1155*a58d3d2aSXin Li 
1156*a58d3d2aSXin Li     fclose(f_in_features);
1157*a58d3d2aSXin Li     fclose(f_out_features);
1158*a58d3d2aSXin Li     fclose(f_numbits);
1159*a58d3d2aSXin Li     fclose(f_periods);
1160*a58d3d2aSXin Li }
1161*a58d3d2aSXin Li 
1162*a58d3d2aSXin Li 
1163*a58d3d2aSXin Li void lace_demo(
1164*a58d3d2aSXin Li     char *prefix,
1165*a58d3d2aSXin Li     char *output
1166*a58d3d2aSXin Li )
1167*a58d3d2aSXin Li {
1168*a58d3d2aSXin Li     char feature_file[256];
1169*a58d3d2aSXin Li     char numbits_file[256];
1170*a58d3d2aSXin Li     char periods_file[256];
1171*a58d3d2aSXin Li     char x_in_file[256];
1172*a58d3d2aSXin Li     char message[512];
1173*a58d3d2aSXin Li     int i_frame;
1174*a58d3d2aSXin Li     float mse;
1175*a58d3d2aSXin Li     float features[4 * LACE_NUM_FEATURES];
1176*a58d3d2aSXin Li     float numbits[2];
1177*a58d3d2aSXin Li     int periods[4];
1178*a58d3d2aSXin Li     float x_in[4 * LACE_FRAME_SIZE];
1179*a58d3d2aSXin Li     int16_t x_out[4 * LACE_FRAME_SIZE];
1180*a58d3d2aSXin Li     float buffer[4 * LACE_FRAME_SIZE];
1181*a58d3d2aSXin Li     LACE hLACE;
1182*a58d3d2aSXin Li     int frame_counter = 0;
1183*a58d3d2aSXin Li     FILE *f_features, *f_numbits, *f_periods, *f_x_in, *f_x_out;
1184*a58d3d2aSXin Li 
1185*a58d3d2aSXin Li     init_lace(&hLACE);
1186*a58d3d2aSXin Li 
1187*a58d3d2aSXin Li     strcpy(feature_file, prefix);
1188*a58d3d2aSXin Li     strcat(feature_file, "_features.f32");
1189*a58d3d2aSXin Li     f_features = fopen(feature_file, "rb");
1190*a58d3d2aSXin Li     if (f_features == NULL)
1191*a58d3d2aSXin Li     {
1192*a58d3d2aSXin Li         sprintf(message, "could not open file %s", feature_file);
1193*a58d3d2aSXin Li         perror(message);
1194*a58d3d2aSXin Li         exit(1);
1195*a58d3d2aSXin Li     }
1196*a58d3d2aSXin Li 
1197*a58d3d2aSXin Li     strcpy(x_in_file, prefix);
1198*a58d3d2aSXin Li     strcat(x_in_file, "_x_in.f32");
1199*a58d3d2aSXin Li     f_x_in = fopen(x_in_file, "rb");
1200*a58d3d2aSXin Li     if (f_x_in == NULL)
1201*a58d3d2aSXin Li     {
1202*a58d3d2aSXin Li         sprintf(message, "could not open file %s", x_in_file);
1203*a58d3d2aSXin Li         perror(message);
1204*a58d3d2aSXin Li         exit(1);
1205*a58d3d2aSXin Li     }
1206*a58d3d2aSXin Li 
1207*a58d3d2aSXin Li     f_x_out = fopen(output, "wb");
1208*a58d3d2aSXin Li     if (f_x_out == NULL)
1209*a58d3d2aSXin Li     {
1210*a58d3d2aSXin Li         sprintf(message, "could not open file %s", output);
1211*a58d3d2aSXin Li         perror(message);
1212*a58d3d2aSXin Li         exit(1);
1213*a58d3d2aSXin Li     }
1214*a58d3d2aSXin Li 
1215*a58d3d2aSXin Li     strcpy(periods_file, prefix);
1216*a58d3d2aSXin Li     strcat(periods_file, "_periods.s32");
1217*a58d3d2aSXin Li     f_periods = fopen(periods_file, "rb");
1218*a58d3d2aSXin Li     if (f_periods == NULL)
1219*a58d3d2aSXin Li     {
1220*a58d3d2aSXin Li         sprintf(message, "could not open file %s", periods_file);
1221*a58d3d2aSXin Li         perror(message);
1222*a58d3d2aSXin Li         exit(1);
1223*a58d3d2aSXin Li     }
1224*a58d3d2aSXin Li 
1225*a58d3d2aSXin Li     strcpy(numbits_file, prefix);
1226*a58d3d2aSXin Li     strcat(numbits_file, "_numbits.f32");
1227*a58d3d2aSXin Li     f_numbits = fopen(numbits_file, "rb");
1228*a58d3d2aSXin Li     if (f_numbits == NULL)
1229*a58d3d2aSXin Li     {
1230*a58d3d2aSXin Li         sprintf(message, "could not open file %s", numbits_file);
1231*a58d3d2aSXin Li         perror(message);
1232*a58d3d2aSXin Li         exit(1);
1233*a58d3d2aSXin Li     }
1234*a58d3d2aSXin Li 
1235*a58d3d2aSXin Li     printf("processing %s\n", prefix);
1236*a58d3d2aSXin Li 
1237*a58d3d2aSXin Li     while (fread(x_in, sizeof(float), 4 * LACE_FRAME_SIZE, f_x_in) == 4 * LACE_FRAME_SIZE)
1238*a58d3d2aSXin Li     {
1239*a58d3d2aSXin Li         printf("\rframe: %d", frame_counter++);
1240*a58d3d2aSXin Li         if(fread(features, sizeof(float), 4 * LACE_NUM_FEATURES, f_features) != 4 * LACE_NUM_FEATURES)
1241*a58d3d2aSXin Li         {
1242*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from features\n", i_frame);
1243*a58d3d2aSXin Li             exit(1);
1244*a58d3d2aSXin Li         }
1245*a58d3d2aSXin Li         if(fread(periods, sizeof(int), 4, f_periods) != 4)
1246*a58d3d2aSXin Li         {
1247*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from periods\n", i_frame);
1248*a58d3d2aSXin Li             exit(1);
1249*a58d3d2aSXin Li         }
1250*a58d3d2aSXin Li         if(fread(numbits, sizeof(float), 2, f_numbits) != 2)
1251*a58d3d2aSXin Li         {
1252*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from numbits\n", i_frame);
1253*a58d3d2aSXin Li             exit(1);
1254*a58d3d2aSXin Li         }
1255*a58d3d2aSXin Li 
1256*a58d3d2aSXin Li         lace_process_20ms_frame(
1257*a58d3d2aSXin Li             &hLACE,
1258*a58d3d2aSXin Li             buffer,
1259*a58d3d2aSXin Li             x_in,
1260*a58d3d2aSXin Li             features,
1261*a58d3d2aSXin Li             numbits,
1262*a58d3d2aSXin Li             periods
1263*a58d3d2aSXin Li         );
1264*a58d3d2aSXin Li 
1265*a58d3d2aSXin Li         for (int n=0; n < 4 * LACE_FRAME_SIZE; n ++)
1266*a58d3d2aSXin Li         {
1267*a58d3d2aSXin Li             float tmp = (1UL<<15) * buffer[n];
1268*a58d3d2aSXin Li             tmp = CLIP(tmp, -32768, 32767);
1269*a58d3d2aSXin Li             x_out[n] = (int16_t) round(tmp);
1270*a58d3d2aSXin Li         }
1271*a58d3d2aSXin Li 
1272*a58d3d2aSXin Li         fwrite(x_out, sizeof(int16_t), 4 * LACE_FRAME_SIZE, f_x_out);
1273*a58d3d2aSXin Li     }
1274*a58d3d2aSXin Li     printf("\ndone!\n");
1275*a58d3d2aSXin Li 
1276*a58d3d2aSXin Li     fclose(f_features);
1277*a58d3d2aSXin Li     fclose(f_numbits);
1278*a58d3d2aSXin Li     fclose(f_periods);
1279*a58d3d2aSXin Li     fclose(f_x_in);
1280*a58d3d2aSXin Li     fclose(f_x_out);
1281*a58d3d2aSXin Li }
1282*a58d3d2aSXin Li 
1283*a58d3d2aSXin Li void nolace_demo(
1284*a58d3d2aSXin Li     char *prefix,
1285*a58d3d2aSXin Li     char *output
1286*a58d3d2aSXin Li )
1287*a58d3d2aSXin Li {
1288*a58d3d2aSXin Li     char feature_file[256];
1289*a58d3d2aSXin Li     char numbits_file[256];
1290*a58d3d2aSXin Li     char periods_file[256];
1291*a58d3d2aSXin Li     char x_in_file[256];
1292*a58d3d2aSXin Li     char message[512];
1293*a58d3d2aSXin Li     int i_frame;
1294*a58d3d2aSXin Li     float mse;
1295*a58d3d2aSXin Li     float features[4 * LACE_NUM_FEATURES];
1296*a58d3d2aSXin Li     float numbits[2];
1297*a58d3d2aSXin Li     int periods[4];
1298*a58d3d2aSXin Li     float x_in[4 * LACE_FRAME_SIZE];
1299*a58d3d2aSXin Li     int16_t x_out[4 * LACE_FRAME_SIZE];
1300*a58d3d2aSXin Li     float buffer[4 * LACE_FRAME_SIZE];
1301*a58d3d2aSXin Li     NoLACE hNoLACE;
1302*a58d3d2aSXin Li     int frame_counter = 0;
1303*a58d3d2aSXin Li     FILE *f_features, *f_numbits, *f_periods, *f_x_in, *f_x_out;
1304*a58d3d2aSXin Li 
1305*a58d3d2aSXin Li     init_nolace(&hNoLACE);
1306*a58d3d2aSXin Li 
1307*a58d3d2aSXin Li     strcpy(feature_file, prefix);
1308*a58d3d2aSXin Li     strcat(feature_file, "_features.f32");
1309*a58d3d2aSXin Li     f_features = fopen(feature_file, "rb");
1310*a58d3d2aSXin Li     if (f_features == NULL)
1311*a58d3d2aSXin Li     {
1312*a58d3d2aSXin Li         sprintf(message, "could not open file %s", feature_file);
1313*a58d3d2aSXin Li         perror(message);
1314*a58d3d2aSXin Li         exit(1);
1315*a58d3d2aSXin Li     }
1316*a58d3d2aSXin Li 
1317*a58d3d2aSXin Li     strcpy(x_in_file, prefix);
1318*a58d3d2aSXin Li     strcat(x_in_file, "_x_in.f32");
1319*a58d3d2aSXin Li     f_x_in = fopen(x_in_file, "rb");
1320*a58d3d2aSXin Li     if (f_x_in == NULL)
1321*a58d3d2aSXin Li     {
1322*a58d3d2aSXin Li         sprintf(message, "could not open file %s", x_in_file);
1323*a58d3d2aSXin Li         perror(message);
1324*a58d3d2aSXin Li         exit(1);
1325*a58d3d2aSXin Li     }
1326*a58d3d2aSXin Li 
1327*a58d3d2aSXin Li     f_x_out = fopen(output, "wb");
1328*a58d3d2aSXin Li     if (f_x_out == NULL)
1329*a58d3d2aSXin Li     {
1330*a58d3d2aSXin Li         sprintf(message, "could not open file %s", output);
1331*a58d3d2aSXin Li         perror(message);
1332*a58d3d2aSXin Li         exit(1);
1333*a58d3d2aSXin Li     }
1334*a58d3d2aSXin Li 
1335*a58d3d2aSXin Li     strcpy(periods_file, prefix);
1336*a58d3d2aSXin Li     strcat(periods_file, "_periods.s32");
1337*a58d3d2aSXin Li     f_periods = fopen(periods_file, "rb");
1338*a58d3d2aSXin Li     if (f_periods == NULL)
1339*a58d3d2aSXin Li     {
1340*a58d3d2aSXin Li         sprintf(message, "could not open file %s", periods_file);
1341*a58d3d2aSXin Li         perror(message);
1342*a58d3d2aSXin Li         exit(1);
1343*a58d3d2aSXin Li     }
1344*a58d3d2aSXin Li 
1345*a58d3d2aSXin Li     strcpy(numbits_file, prefix);
1346*a58d3d2aSXin Li     strcat(numbits_file, "_numbits.f32");
1347*a58d3d2aSXin Li     f_numbits = fopen(numbits_file, "rb");
1348*a58d3d2aSXin Li     if (f_numbits == NULL)
1349*a58d3d2aSXin Li     {
1350*a58d3d2aSXin Li         sprintf(message, "could not open file %s", numbits_file);
1351*a58d3d2aSXin Li         perror(message);
1352*a58d3d2aSXin Li         exit(1);
1353*a58d3d2aSXin Li     }
1354*a58d3d2aSXin Li 
1355*a58d3d2aSXin Li     printf("processing %s\n", prefix);
1356*a58d3d2aSXin Li 
1357*a58d3d2aSXin Li     while (fread(x_in, sizeof(float), 4 * LACE_FRAME_SIZE, f_x_in) == 4 * LACE_FRAME_SIZE)
1358*a58d3d2aSXin Li     {
1359*a58d3d2aSXin Li         printf("\rframe: %d", frame_counter++);
1360*a58d3d2aSXin Li         if(fread(features, sizeof(float), 4 * LACE_NUM_FEATURES, f_features) != 4 * LACE_NUM_FEATURES)
1361*a58d3d2aSXin Li         {
1362*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from features\n", i_frame);
1363*a58d3d2aSXin Li             exit(1);
1364*a58d3d2aSXin Li         }
1365*a58d3d2aSXin Li         if(fread(periods, sizeof(int), 4, f_periods) != 4)
1366*a58d3d2aSXin Li         {
1367*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from periods\n", i_frame);
1368*a58d3d2aSXin Li             exit(1);
1369*a58d3d2aSXin Li         }
1370*a58d3d2aSXin Li         if(fread(numbits, sizeof(float), 2, f_numbits) != 2)
1371*a58d3d2aSXin Li         {
1372*a58d3d2aSXin Li             fprintf(stderr, "could not read frame %d from numbits\n", i_frame);
1373*a58d3d2aSXin Li             exit(1);
1374*a58d3d2aSXin Li         }
1375*a58d3d2aSXin Li 
1376*a58d3d2aSXin Li         nolace_process_20ms_frame(
1377*a58d3d2aSXin Li             &hNoLACE,
1378*a58d3d2aSXin Li             buffer,
1379*a58d3d2aSXin Li             x_in,
1380*a58d3d2aSXin Li             features,
1381*a58d3d2aSXin Li             numbits,
1382*a58d3d2aSXin Li             periods
1383*a58d3d2aSXin Li         );
1384*a58d3d2aSXin Li 
1385*a58d3d2aSXin Li         for (int n=0; n < 4 * LACE_FRAME_SIZE; n ++)
1386*a58d3d2aSXin Li         {
1387*a58d3d2aSXin Li             float tmp = (1UL<<15) * buffer[n];
1388*a58d3d2aSXin Li             tmp = CLIP(tmp, -32768, 32767);
1389*a58d3d2aSXin Li             x_out[n] = (int16_t) round(tmp);
1390*a58d3d2aSXin Li         }
1391*a58d3d2aSXin Li 
1392*a58d3d2aSXin Li         fwrite(x_out, sizeof(int16_t), 4 * LACE_FRAME_SIZE, f_x_out);
1393*a58d3d2aSXin Li     }
1394*a58d3d2aSXin Li     printf("\ndone!\n");
1395*a58d3d2aSXin Li 
1396*a58d3d2aSXin Li     fclose(f_features);
1397*a58d3d2aSXin Li     fclose(f_numbits);
1398*a58d3d2aSXin Li     fclose(f_periods);
1399*a58d3d2aSXin Li     fclose(f_x_in);
1400*a58d3d2aSXin Li     fclose(f_x_out);
1401*a58d3d2aSXin Li }
1402*a58d3d2aSXin Li 
1403*a58d3d2aSXin Li 
1404*a58d3d2aSXin Li int main()
1405*a58d3d2aSXin Li {
1406*a58d3d2aSXin Li #if 0
1407*a58d3d2aSXin Li     LACE hLACE;
1408*a58d3d2aSXin Li 
1409*a58d3d2aSXin Li     lace_feature_net_compare("testvec2/lace", 5, &hLACE);
1410*a58d3d2aSXin Li 
1411*a58d3d2aSXin Li     lace_demo("testdata/test9", "out_lace_c_9kbps.pcm");
1412*a58d3d2aSXin Li     lace_demo("testdata/test6", "out_lace_c_6kbps.pcm");
1413*a58d3d2aSXin Li #endif
1414*a58d3d2aSXin Li     nolace_demo("testdata/test9", "out_nolace_c_9kbps.pcm");
1415*a58d3d2aSXin Li 
1416*a58d3d2aSXin Li }
1417*a58d3d2aSXin Li #endif
1418*a58d3d2aSXin Li 
1419*a58d3d2aSXin Li /*gcc  -I ../include -I . -I ../silk -I ../celt osce.c nndsp.c lace_data.c nolace_data.c nnet.c parse_lpcnet_weights.c -lm -o lacetest*/
1420