xref: /aosp_15_r20/external/libopus/src/opus_decoder.c (revision a58d3d2adb790c104798cd88c8a3aff4fa8b82cc)
1*a58d3d2aSXin Li /* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
2*a58d3d2aSXin Li    Written by Jean-Marc Valin and Koen Vos */
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 #ifndef OPUS_BUILD
33*a58d3d2aSXin Li # error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details."
34*a58d3d2aSXin Li #endif
35*a58d3d2aSXin Li 
36*a58d3d2aSXin Li #if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__) && !defined(OPUS_WILL_BE_SLOW)
37*a58d3d2aSXin Li # pragma message "You appear to be compiling without optimization, if so opus will be very slow."
38*a58d3d2aSXin Li #endif
39*a58d3d2aSXin Li 
40*a58d3d2aSXin Li #include <stdarg.h>
41*a58d3d2aSXin Li #include "celt.h"
42*a58d3d2aSXin Li #include "opus.h"
43*a58d3d2aSXin Li #include "entdec.h"
44*a58d3d2aSXin Li #include "modes.h"
45*a58d3d2aSXin Li #include "API.h"
46*a58d3d2aSXin Li #include "stack_alloc.h"
47*a58d3d2aSXin Li #include "float_cast.h"
48*a58d3d2aSXin Li #include "opus_private.h"
49*a58d3d2aSXin Li #include "os_support.h"
50*a58d3d2aSXin Li #include "structs.h"
51*a58d3d2aSXin Li #include "define.h"
52*a58d3d2aSXin Li #include "mathops.h"
53*a58d3d2aSXin Li #include "cpu_support.h"
54*a58d3d2aSXin Li 
55*a58d3d2aSXin Li #ifdef ENABLE_DEEP_PLC
56*a58d3d2aSXin Li #include "dred_rdovae_dec_data.h"
57*a58d3d2aSXin Li #include "dred_rdovae_dec.h"
58*a58d3d2aSXin Li #endif
59*a58d3d2aSXin Li 
60*a58d3d2aSXin Li #ifdef ENABLE_OSCE
61*a58d3d2aSXin Li #include "osce.h"
62*a58d3d2aSXin Li #endif
63*a58d3d2aSXin Li 
64*a58d3d2aSXin Li struct OpusDecoder {
65*a58d3d2aSXin Li    int          celt_dec_offset;
66*a58d3d2aSXin Li    int          silk_dec_offset;
67*a58d3d2aSXin Li    int          channels;
68*a58d3d2aSXin Li    opus_int32   Fs;          /** Sampling rate (at the API level) */
69*a58d3d2aSXin Li    silk_DecControlStruct DecControl;
70*a58d3d2aSXin Li    int          decode_gain;
71*a58d3d2aSXin Li    int          complexity;
72*a58d3d2aSXin Li    int          arch;
73*a58d3d2aSXin Li #ifdef ENABLE_DEEP_PLC
74*a58d3d2aSXin Li     LPCNetPLCState lpcnet;
75*a58d3d2aSXin Li #endif
76*a58d3d2aSXin Li 
77*a58d3d2aSXin Li    /* Everything beyond this point gets cleared on a reset */
78*a58d3d2aSXin Li #define OPUS_DECODER_RESET_START stream_channels
79*a58d3d2aSXin Li    int          stream_channels;
80*a58d3d2aSXin Li 
81*a58d3d2aSXin Li    int          bandwidth;
82*a58d3d2aSXin Li    int          mode;
83*a58d3d2aSXin Li    int          prev_mode;
84*a58d3d2aSXin Li    int          frame_size;
85*a58d3d2aSXin Li    int          prev_redundancy;
86*a58d3d2aSXin Li    int          last_packet_duration;
87*a58d3d2aSXin Li #ifndef FIXED_POINT
88*a58d3d2aSXin Li    opus_val16   softclip_mem[2];
89*a58d3d2aSXin Li #endif
90*a58d3d2aSXin Li 
91*a58d3d2aSXin Li    opus_uint32  rangeFinal;
92*a58d3d2aSXin Li };
93*a58d3d2aSXin Li 
94*a58d3d2aSXin Li #if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
validate_opus_decoder(OpusDecoder * st)95*a58d3d2aSXin Li static void validate_opus_decoder(OpusDecoder *st)
96*a58d3d2aSXin Li {
97*a58d3d2aSXin Li    celt_assert(st->channels == 1 || st->channels == 2);
98*a58d3d2aSXin Li    celt_assert(st->Fs == 48000 || st->Fs == 24000 || st->Fs == 16000 || st->Fs == 12000 || st->Fs == 8000);
99*a58d3d2aSXin Li    celt_assert(st->DecControl.API_sampleRate == st->Fs);
100*a58d3d2aSXin Li    celt_assert(st->DecControl.internalSampleRate == 0 || st->DecControl.internalSampleRate == 16000 || st->DecControl.internalSampleRate == 12000 || st->DecControl.internalSampleRate == 8000);
101*a58d3d2aSXin Li    celt_assert(st->DecControl.nChannelsAPI == st->channels);
102*a58d3d2aSXin Li    celt_assert(st->DecControl.nChannelsInternal == 0 || st->DecControl.nChannelsInternal == 1 || st->DecControl.nChannelsInternal == 2);
103*a58d3d2aSXin Li    celt_assert(st->DecControl.payloadSize_ms == 0 || st->DecControl.payloadSize_ms == 10 || st->DecControl.payloadSize_ms == 20 || st->DecControl.payloadSize_ms == 40 || st->DecControl.payloadSize_ms == 60);
104*a58d3d2aSXin Li #ifdef OPUS_ARCHMASK
105*a58d3d2aSXin Li    celt_assert(st->arch >= 0);
106*a58d3d2aSXin Li    celt_assert(st->arch <= OPUS_ARCHMASK);
107*a58d3d2aSXin Li #endif
108*a58d3d2aSXin Li    celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
109*a58d3d2aSXin Li }
110*a58d3d2aSXin Li #define VALIDATE_OPUS_DECODER(st) validate_opus_decoder(st)
111*a58d3d2aSXin Li #else
112*a58d3d2aSXin Li #define VALIDATE_OPUS_DECODER(st)
113*a58d3d2aSXin Li #endif
114*a58d3d2aSXin Li 
opus_decoder_get_size(int channels)115*a58d3d2aSXin Li int opus_decoder_get_size(int channels)
116*a58d3d2aSXin Li {
117*a58d3d2aSXin Li    int silkDecSizeBytes, celtDecSizeBytes;
118*a58d3d2aSXin Li    int ret;
119*a58d3d2aSXin Li    if (channels<1 || channels > 2)
120*a58d3d2aSXin Li       return 0;
121*a58d3d2aSXin Li    ret = silk_Get_Decoder_Size( &silkDecSizeBytes );
122*a58d3d2aSXin Li    if(ret)
123*a58d3d2aSXin Li       return 0;
124*a58d3d2aSXin Li    silkDecSizeBytes = align(silkDecSizeBytes);
125*a58d3d2aSXin Li    celtDecSizeBytes = celt_decoder_get_size(channels);
126*a58d3d2aSXin Li    return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes;
127*a58d3d2aSXin Li }
128*a58d3d2aSXin Li 
opus_decoder_init(OpusDecoder * st,opus_int32 Fs,int channels)129*a58d3d2aSXin Li int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
130*a58d3d2aSXin Li {
131*a58d3d2aSXin Li    void *silk_dec;
132*a58d3d2aSXin Li    CELTDecoder *celt_dec;
133*a58d3d2aSXin Li    int ret, silkDecSizeBytes;
134*a58d3d2aSXin Li 
135*a58d3d2aSXin Li    if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)
136*a58d3d2aSXin Li     || (channels!=1&&channels!=2))
137*a58d3d2aSXin Li       return OPUS_BAD_ARG;
138*a58d3d2aSXin Li 
139*a58d3d2aSXin Li    OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
140*a58d3d2aSXin Li    /* Initialize SILK decoder */
141*a58d3d2aSXin Li    ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
142*a58d3d2aSXin Li    if (ret)
143*a58d3d2aSXin Li       return OPUS_INTERNAL_ERROR;
144*a58d3d2aSXin Li 
145*a58d3d2aSXin Li    silkDecSizeBytes = align(silkDecSizeBytes);
146*a58d3d2aSXin Li    st->silk_dec_offset = align(sizeof(OpusDecoder));
147*a58d3d2aSXin Li    st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes;
148*a58d3d2aSXin Li    silk_dec = (char*)st+st->silk_dec_offset;
149*a58d3d2aSXin Li    celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
150*a58d3d2aSXin Li    st->stream_channels = st->channels = channels;
151*a58d3d2aSXin Li    st->complexity = 0;
152*a58d3d2aSXin Li 
153*a58d3d2aSXin Li    st->Fs = Fs;
154*a58d3d2aSXin Li    st->DecControl.API_sampleRate = st->Fs;
155*a58d3d2aSXin Li    st->DecControl.nChannelsAPI      = st->channels;
156*a58d3d2aSXin Li 
157*a58d3d2aSXin Li    /* Reset decoder */
158*a58d3d2aSXin Li    ret = silk_InitDecoder( silk_dec );
159*a58d3d2aSXin Li    if(ret)return OPUS_INTERNAL_ERROR;
160*a58d3d2aSXin Li 
161*a58d3d2aSXin Li    /* Initialize CELT decoder */
162*a58d3d2aSXin Li    ret = celt_decoder_init(celt_dec, Fs, channels);
163*a58d3d2aSXin Li    if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR;
164*a58d3d2aSXin Li 
165*a58d3d2aSXin Li    celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));
166*a58d3d2aSXin Li 
167*a58d3d2aSXin Li    st->prev_mode = 0;
168*a58d3d2aSXin Li    st->frame_size = Fs/400;
169*a58d3d2aSXin Li #ifdef ENABLE_DEEP_PLC
170*a58d3d2aSXin Li     lpcnet_plc_init( &st->lpcnet);
171*a58d3d2aSXin Li #endif
172*a58d3d2aSXin Li    st->arch = opus_select_arch();
173*a58d3d2aSXin Li    return OPUS_OK;
174*a58d3d2aSXin Li }
175*a58d3d2aSXin Li 
opus_decoder_create(opus_int32 Fs,int channels,int * error)176*a58d3d2aSXin Li OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error)
177*a58d3d2aSXin Li {
178*a58d3d2aSXin Li    int ret;
179*a58d3d2aSXin Li    OpusDecoder *st;
180*a58d3d2aSXin Li    if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)
181*a58d3d2aSXin Li     || (channels!=1&&channels!=2))
182*a58d3d2aSXin Li    {
183*a58d3d2aSXin Li       if (error)
184*a58d3d2aSXin Li          *error = OPUS_BAD_ARG;
185*a58d3d2aSXin Li       return NULL;
186*a58d3d2aSXin Li    }
187*a58d3d2aSXin Li    st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels));
188*a58d3d2aSXin Li    if (st == NULL)
189*a58d3d2aSXin Li    {
190*a58d3d2aSXin Li       if (error)
191*a58d3d2aSXin Li          *error = OPUS_ALLOC_FAIL;
192*a58d3d2aSXin Li       return NULL;
193*a58d3d2aSXin Li    }
194*a58d3d2aSXin Li    ret = opus_decoder_init(st, Fs, channels);
195*a58d3d2aSXin Li    if (error)
196*a58d3d2aSXin Li       *error = ret;
197*a58d3d2aSXin Li    if (ret != OPUS_OK)
198*a58d3d2aSXin Li    {
199*a58d3d2aSXin Li       opus_free(st);
200*a58d3d2aSXin Li       st = NULL;
201*a58d3d2aSXin Li    }
202*a58d3d2aSXin Li    return st;
203*a58d3d2aSXin Li }
204*a58d3d2aSXin Li 
smooth_fade(const opus_val16 * in1,const opus_val16 * in2,opus_val16 * out,int overlap,int channels,const opus_val16 * window,opus_int32 Fs)205*a58d3d2aSXin Li static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2,
206*a58d3d2aSXin Li       opus_val16 *out, int overlap, int channels,
207*a58d3d2aSXin Li       const opus_val16 *window, opus_int32 Fs)
208*a58d3d2aSXin Li {
209*a58d3d2aSXin Li    int i, c;
210*a58d3d2aSXin Li    int inc = 48000/Fs;
211*a58d3d2aSXin Li    for (c=0;c<channels;c++)
212*a58d3d2aSXin Li    {
213*a58d3d2aSXin Li       for (i=0;i<overlap;i++)
214*a58d3d2aSXin Li       {
215*a58d3d2aSXin Li          opus_val16 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
216*a58d3d2aSXin Li          out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]),
217*a58d3d2aSXin Li                                    Q15ONE-w, in1[i*channels+c]), 15);
218*a58d3d2aSXin Li       }
219*a58d3d2aSXin Li    }
220*a58d3d2aSXin Li }
221*a58d3d2aSXin Li 
opus_packet_get_mode(const unsigned char * data)222*a58d3d2aSXin Li static int opus_packet_get_mode(const unsigned char *data)
223*a58d3d2aSXin Li {
224*a58d3d2aSXin Li    int mode;
225*a58d3d2aSXin Li    if (data[0]&0x80)
226*a58d3d2aSXin Li    {
227*a58d3d2aSXin Li       mode = MODE_CELT_ONLY;
228*a58d3d2aSXin Li    } else if ((data[0]&0x60) == 0x60)
229*a58d3d2aSXin Li    {
230*a58d3d2aSXin Li       mode = MODE_HYBRID;
231*a58d3d2aSXin Li    } else {
232*a58d3d2aSXin Li       mode = MODE_SILK_ONLY;
233*a58d3d2aSXin Li    }
234*a58d3d2aSXin Li    return mode;
235*a58d3d2aSXin Li }
236*a58d3d2aSXin Li 
opus_decode_frame(OpusDecoder * st,const unsigned char * data,opus_int32 len,opus_val16 * pcm,int frame_size,int decode_fec)237*a58d3d2aSXin Li static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
238*a58d3d2aSXin Li       opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
239*a58d3d2aSXin Li {
240*a58d3d2aSXin Li    void *silk_dec;
241*a58d3d2aSXin Li    CELTDecoder *celt_dec;
242*a58d3d2aSXin Li    int i, silk_ret=0, celt_ret=0;
243*a58d3d2aSXin Li    ec_dec dec;
244*a58d3d2aSXin Li    opus_int32 silk_frame_size;
245*a58d3d2aSXin Li    int pcm_silk_size;
246*a58d3d2aSXin Li    VARDECL(opus_int16, pcm_silk);
247*a58d3d2aSXin Li    int pcm_transition_silk_size;
248*a58d3d2aSXin Li    VARDECL(opus_val16, pcm_transition_silk);
249*a58d3d2aSXin Li    int pcm_transition_celt_size;
250*a58d3d2aSXin Li    VARDECL(opus_val16, pcm_transition_celt);
251*a58d3d2aSXin Li    opus_val16 *pcm_transition=NULL;
252*a58d3d2aSXin Li    int redundant_audio_size;
253*a58d3d2aSXin Li    VARDECL(opus_val16, redundant_audio);
254*a58d3d2aSXin Li 
255*a58d3d2aSXin Li    int audiosize;
256*a58d3d2aSXin Li    int mode;
257*a58d3d2aSXin Li    int bandwidth;
258*a58d3d2aSXin Li    int transition=0;
259*a58d3d2aSXin Li    int start_band;
260*a58d3d2aSXin Li    int redundancy=0;
261*a58d3d2aSXin Li    int redundancy_bytes = 0;
262*a58d3d2aSXin Li    int celt_to_silk=0;
263*a58d3d2aSXin Li    int c;
264*a58d3d2aSXin Li    int F2_5, F5, F10, F20;
265*a58d3d2aSXin Li    const opus_val16 *window;
266*a58d3d2aSXin Li    opus_uint32 redundant_rng = 0;
267*a58d3d2aSXin Li    int celt_accum;
268*a58d3d2aSXin Li    ALLOC_STACK;
269*a58d3d2aSXin Li 
270*a58d3d2aSXin Li    silk_dec = (char*)st+st->silk_dec_offset;
271*a58d3d2aSXin Li    celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
272*a58d3d2aSXin Li    F20 = st->Fs/50;
273*a58d3d2aSXin Li    F10 = F20>>1;
274*a58d3d2aSXin Li    F5 = F10>>1;
275*a58d3d2aSXin Li    F2_5 = F5>>1;
276*a58d3d2aSXin Li    if (frame_size < F2_5)
277*a58d3d2aSXin Li    {
278*a58d3d2aSXin Li       RESTORE_STACK;
279*a58d3d2aSXin Li       return OPUS_BUFFER_TOO_SMALL;
280*a58d3d2aSXin Li    }
281*a58d3d2aSXin Li    /* Limit frame_size to avoid excessive stack allocations. */
282*a58d3d2aSXin Li    frame_size = IMIN(frame_size, st->Fs/25*3);
283*a58d3d2aSXin Li    /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
284*a58d3d2aSXin Li    if (len<=1)
285*a58d3d2aSXin Li    {
286*a58d3d2aSXin Li       data = NULL;
287*a58d3d2aSXin Li       /* In that case, don't conceal more than what the ToC says */
288*a58d3d2aSXin Li       frame_size = IMIN(frame_size, st->frame_size);
289*a58d3d2aSXin Li    }
290*a58d3d2aSXin Li    if (data != NULL)
291*a58d3d2aSXin Li    {
292*a58d3d2aSXin Li       audiosize = st->frame_size;
293*a58d3d2aSXin Li       mode = st->mode;
294*a58d3d2aSXin Li       bandwidth = st->bandwidth;
295*a58d3d2aSXin Li       ec_dec_init(&dec,(unsigned char*)data,len);
296*a58d3d2aSXin Li    } else {
297*a58d3d2aSXin Li       audiosize = frame_size;
298*a58d3d2aSXin Li       /* Run PLC using last used mode (CELT if we ended with CELT redundancy) */
299*a58d3d2aSXin Li       mode = st->prev_redundancy ? MODE_CELT_ONLY : st->prev_mode;
300*a58d3d2aSXin Li       bandwidth = 0;
301*a58d3d2aSXin Li 
302*a58d3d2aSXin Li       if (mode == 0)
303*a58d3d2aSXin Li       {
304*a58d3d2aSXin Li          /* If we haven't got any packet yet, all we can do is return zeros */
305*a58d3d2aSXin Li          for (i=0;i<audiosize*st->channels;i++)
306*a58d3d2aSXin Li             pcm[i] = 0;
307*a58d3d2aSXin Li          RESTORE_STACK;
308*a58d3d2aSXin Li          return audiosize;
309*a58d3d2aSXin Li       }
310*a58d3d2aSXin Li 
311*a58d3d2aSXin Li       /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
312*a58d3d2aSXin Li          10, or 20 (e.g. 12.5 or 30 ms). */
313*a58d3d2aSXin Li       if (audiosize > F20)
314*a58d3d2aSXin Li       {
315*a58d3d2aSXin Li          do {
316*a58d3d2aSXin Li             int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0);
317*a58d3d2aSXin Li             if (ret<0)
318*a58d3d2aSXin Li             {
319*a58d3d2aSXin Li                RESTORE_STACK;
320*a58d3d2aSXin Li                return ret;
321*a58d3d2aSXin Li             }
322*a58d3d2aSXin Li             pcm += ret*st->channels;
323*a58d3d2aSXin Li             audiosize -= ret;
324*a58d3d2aSXin Li          } while (audiosize > 0);
325*a58d3d2aSXin Li          RESTORE_STACK;
326*a58d3d2aSXin Li          return frame_size;
327*a58d3d2aSXin Li       } else if (audiosize < F20)
328*a58d3d2aSXin Li       {
329*a58d3d2aSXin Li          if (audiosize > F10)
330*a58d3d2aSXin Li             audiosize = F10;
331*a58d3d2aSXin Li          else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
332*a58d3d2aSXin Li             audiosize = F5;
333*a58d3d2aSXin Li       }
334*a58d3d2aSXin Li    }
335*a58d3d2aSXin Li 
336*a58d3d2aSXin Li    /* In fixed-point, we can tell CELT to do the accumulation on top of the
337*a58d3d2aSXin Li       SILK PCM buffer. This saves some stack space. */
338*a58d3d2aSXin Li #ifdef FIXED_POINT
339*a58d3d2aSXin Li    celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10);
340*a58d3d2aSXin Li #else
341*a58d3d2aSXin Li    celt_accum = 0;
342*a58d3d2aSXin Li #endif
343*a58d3d2aSXin Li 
344*a58d3d2aSXin Li    pcm_transition_silk_size = ALLOC_NONE;
345*a58d3d2aSXin Li    pcm_transition_celt_size = ALLOC_NONE;
346*a58d3d2aSXin Li    if (data!=NULL && st->prev_mode > 0 && (
347*a58d3d2aSXin Li        (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
348*a58d3d2aSXin Li     || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
349*a58d3d2aSXin Li       )
350*a58d3d2aSXin Li    {
351*a58d3d2aSXin Li       transition = 1;
352*a58d3d2aSXin Li       /* Decide where to allocate the stack memory for pcm_transition */
353*a58d3d2aSXin Li       if (mode == MODE_CELT_ONLY)
354*a58d3d2aSXin Li          pcm_transition_celt_size = F5*st->channels;
355*a58d3d2aSXin Li       else
356*a58d3d2aSXin Li          pcm_transition_silk_size = F5*st->channels;
357*a58d3d2aSXin Li    }
358*a58d3d2aSXin Li    ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16);
359*a58d3d2aSXin Li    if (transition && mode == MODE_CELT_ONLY)
360*a58d3d2aSXin Li    {
361*a58d3d2aSXin Li       pcm_transition = pcm_transition_celt;
362*a58d3d2aSXin Li       opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
363*a58d3d2aSXin Li    }
364*a58d3d2aSXin Li    if (audiosize > frame_size)
365*a58d3d2aSXin Li    {
366*a58d3d2aSXin Li       /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/
367*a58d3d2aSXin Li       RESTORE_STACK;
368*a58d3d2aSXin Li       return OPUS_BAD_ARG;
369*a58d3d2aSXin Li    } else {
370*a58d3d2aSXin Li       frame_size = audiosize;
371*a58d3d2aSXin Li    }
372*a58d3d2aSXin Li 
373*a58d3d2aSXin Li    /* Don't allocate any memory when in CELT-only mode */
374*a58d3d2aSXin Li    pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE;
375*a58d3d2aSXin Li    ALLOC(pcm_silk, pcm_silk_size, opus_int16);
376*a58d3d2aSXin Li 
377*a58d3d2aSXin Li    /* SILK processing */
378*a58d3d2aSXin Li    if (mode != MODE_CELT_ONLY)
379*a58d3d2aSXin Li    {
380*a58d3d2aSXin Li       int lost_flag, decoded_samples;
381*a58d3d2aSXin Li       opus_int16 *pcm_ptr;
382*a58d3d2aSXin Li #ifdef FIXED_POINT
383*a58d3d2aSXin Li       if (celt_accum)
384*a58d3d2aSXin Li          pcm_ptr = pcm;
385*a58d3d2aSXin Li       else
386*a58d3d2aSXin Li #endif
387*a58d3d2aSXin Li          pcm_ptr = pcm_silk;
388*a58d3d2aSXin Li 
389*a58d3d2aSXin Li       if (st->prev_mode==MODE_CELT_ONLY)
390*a58d3d2aSXin Li          silk_ResetDecoder( silk_dec );
391*a58d3d2aSXin Li 
392*a58d3d2aSXin Li       /* The SILK PLC cannot produce frames of less than 10 ms */
393*a58d3d2aSXin Li       st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);
394*a58d3d2aSXin Li 
395*a58d3d2aSXin Li       if (data != NULL)
396*a58d3d2aSXin Li       {
397*a58d3d2aSXin Li         st->DecControl.nChannelsInternal = st->stream_channels;
398*a58d3d2aSXin Li         if( mode == MODE_SILK_ONLY ) {
399*a58d3d2aSXin Li            if( bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
400*a58d3d2aSXin Li               st->DecControl.internalSampleRate = 8000;
401*a58d3d2aSXin Li            } else if( bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
402*a58d3d2aSXin Li               st->DecControl.internalSampleRate = 12000;
403*a58d3d2aSXin Li            } else if( bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
404*a58d3d2aSXin Li               st->DecControl.internalSampleRate = 16000;
405*a58d3d2aSXin Li            } else {
406*a58d3d2aSXin Li               st->DecControl.internalSampleRate = 16000;
407*a58d3d2aSXin Li               celt_assert( 0 );
408*a58d3d2aSXin Li            }
409*a58d3d2aSXin Li         } else {
410*a58d3d2aSXin Li            /* Hybrid mode */
411*a58d3d2aSXin Li            st->DecControl.internalSampleRate = 16000;
412*a58d3d2aSXin Li         }
413*a58d3d2aSXin Li      }
414*a58d3d2aSXin Li      st->DecControl.enable_deep_plc = st->complexity >= 5;
415*a58d3d2aSXin Li #ifdef ENABLE_OSCE
416*a58d3d2aSXin Li      st->DecControl.osce_method = OSCE_METHOD_NONE;
417*a58d3d2aSXin Li #ifndef DISABLE_LACE
418*a58d3d2aSXin Li      if (st->complexity >= 6) {st->DecControl.osce_method = OSCE_METHOD_LACE;}
419*a58d3d2aSXin Li #endif
420*a58d3d2aSXin Li #ifndef DISABLE_NOLACE
421*a58d3d2aSXin Li      if (st->complexity >= 7) {st->DecControl.osce_method = OSCE_METHOD_NOLACE;}
422*a58d3d2aSXin Li #endif
423*a58d3d2aSXin Li #endif
424*a58d3d2aSXin Li 
425*a58d3d2aSXin Li      lost_flag = data == NULL ? 1 : 2 * !!decode_fec;
426*a58d3d2aSXin Li      decoded_samples = 0;
427*a58d3d2aSXin Li      do {
428*a58d3d2aSXin Li         /* Call SILK decoder */
429*a58d3d2aSXin Li         int first_frame = decoded_samples == 0;
430*a58d3d2aSXin Li         silk_ret = silk_Decode( silk_dec, &st->DecControl,
431*a58d3d2aSXin Li                                 lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size,
432*a58d3d2aSXin Li #ifdef ENABLE_DEEP_PLC
433*a58d3d2aSXin Li                                 &st->lpcnet,
434*a58d3d2aSXin Li #endif
435*a58d3d2aSXin Li                                 st->arch );
436*a58d3d2aSXin Li         if( silk_ret ) {
437*a58d3d2aSXin Li            if (lost_flag) {
438*a58d3d2aSXin Li               /* PLC failure should not be fatal */
439*a58d3d2aSXin Li               silk_frame_size = frame_size;
440*a58d3d2aSXin Li               for (i=0;i<frame_size*st->channels;i++)
441*a58d3d2aSXin Li                  pcm_ptr[i] = 0;
442*a58d3d2aSXin Li            } else {
443*a58d3d2aSXin Li              RESTORE_STACK;
444*a58d3d2aSXin Li              return OPUS_INTERNAL_ERROR;
445*a58d3d2aSXin Li            }
446*a58d3d2aSXin Li         }
447*a58d3d2aSXin Li         pcm_ptr += silk_frame_size * st->channels;
448*a58d3d2aSXin Li         decoded_samples += silk_frame_size;
449*a58d3d2aSXin Li       } while( decoded_samples < frame_size );
450*a58d3d2aSXin Li    }
451*a58d3d2aSXin Li 
452*a58d3d2aSXin Li    start_band = 0;
453*a58d3d2aSXin Li    if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
454*a58d3d2aSXin Li     && ec_tell(&dec)+17+20*(mode == MODE_HYBRID) <= 8*len)
455*a58d3d2aSXin Li    {
456*a58d3d2aSXin Li       /* Check if we have a redundant 0-8 kHz band */
457*a58d3d2aSXin Li       if (mode == MODE_HYBRID)
458*a58d3d2aSXin Li          redundancy = ec_dec_bit_logp(&dec, 12);
459*a58d3d2aSXin Li       else
460*a58d3d2aSXin Li          redundancy = 1;
461*a58d3d2aSXin Li       if (redundancy)
462*a58d3d2aSXin Li       {
463*a58d3d2aSXin Li          celt_to_silk = ec_dec_bit_logp(&dec, 1);
464*a58d3d2aSXin Li          /* redundancy_bytes will be at least two, in the non-hybrid
465*a58d3d2aSXin Li             case due to the ec_tell() check above */
466*a58d3d2aSXin Li          redundancy_bytes = mode==MODE_HYBRID ?
467*a58d3d2aSXin Li                (opus_int32)ec_dec_uint(&dec, 256)+2 :
468*a58d3d2aSXin Li                len-((ec_tell(&dec)+7)>>3);
469*a58d3d2aSXin Li          len -= redundancy_bytes;
470*a58d3d2aSXin Li          /* This is a sanity check. It should never happen for a valid
471*a58d3d2aSXin Li             packet, so the exact behaviour is not normative. */
472*a58d3d2aSXin Li          if (len*8 < ec_tell(&dec))
473*a58d3d2aSXin Li          {
474*a58d3d2aSXin Li             len = 0;
475*a58d3d2aSXin Li             redundancy_bytes = 0;
476*a58d3d2aSXin Li             redundancy = 0;
477*a58d3d2aSXin Li          }
478*a58d3d2aSXin Li          /* Shrink decoder because of raw bits */
479*a58d3d2aSXin Li          dec.storage -= redundancy_bytes;
480*a58d3d2aSXin Li       }
481*a58d3d2aSXin Li    }
482*a58d3d2aSXin Li    if (mode != MODE_CELT_ONLY)
483*a58d3d2aSXin Li       start_band = 17;
484*a58d3d2aSXin Li 
485*a58d3d2aSXin Li    if (redundancy)
486*a58d3d2aSXin Li    {
487*a58d3d2aSXin Li       transition = 0;
488*a58d3d2aSXin Li       pcm_transition_silk_size=ALLOC_NONE;
489*a58d3d2aSXin Li    }
490*a58d3d2aSXin Li 
491*a58d3d2aSXin Li    ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);
492*a58d3d2aSXin Li 
493*a58d3d2aSXin Li    if (transition && mode != MODE_CELT_ONLY)
494*a58d3d2aSXin Li    {
495*a58d3d2aSXin Li       pcm_transition = pcm_transition_silk;
496*a58d3d2aSXin Li       opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
497*a58d3d2aSXin Li    }
498*a58d3d2aSXin Li 
499*a58d3d2aSXin Li 
500*a58d3d2aSXin Li    if (bandwidth)
501*a58d3d2aSXin Li    {
502*a58d3d2aSXin Li       int endband=21;
503*a58d3d2aSXin Li 
504*a58d3d2aSXin Li       switch(bandwidth)
505*a58d3d2aSXin Li       {
506*a58d3d2aSXin Li       case OPUS_BANDWIDTH_NARROWBAND:
507*a58d3d2aSXin Li          endband = 13;
508*a58d3d2aSXin Li          break;
509*a58d3d2aSXin Li       case OPUS_BANDWIDTH_MEDIUMBAND:
510*a58d3d2aSXin Li       case OPUS_BANDWIDTH_WIDEBAND:
511*a58d3d2aSXin Li          endband = 17;
512*a58d3d2aSXin Li          break;
513*a58d3d2aSXin Li       case OPUS_BANDWIDTH_SUPERWIDEBAND:
514*a58d3d2aSXin Li          endband = 19;
515*a58d3d2aSXin Li          break;
516*a58d3d2aSXin Li       case OPUS_BANDWIDTH_FULLBAND:
517*a58d3d2aSXin Li          endband = 21;
518*a58d3d2aSXin Li          break;
519*a58d3d2aSXin Li       default:
520*a58d3d2aSXin Li          celt_assert(0);
521*a58d3d2aSXin Li          break;
522*a58d3d2aSXin Li       }
523*a58d3d2aSXin Li       MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)));
524*a58d3d2aSXin Li    }
525*a58d3d2aSXin Li    MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)));
526*a58d3d2aSXin Li 
527*a58d3d2aSXin Li    /* Only allocation memory for redundancy if/when needed */
528*a58d3d2aSXin Li    redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
529*a58d3d2aSXin Li    ALLOC(redundant_audio, redundant_audio_size, opus_val16);
530*a58d3d2aSXin Li 
531*a58d3d2aSXin Li    /* 5 ms redundant frame for CELT->SILK*/
532*a58d3d2aSXin Li    if (redundancy && celt_to_silk)
533*a58d3d2aSXin Li    {
534*a58d3d2aSXin Li       /* If the previous frame did not use CELT (the first redundancy frame in
535*a58d3d2aSXin Li          a transition from SILK may have been lost) then the CELT decoder is
536*a58d3d2aSXin Li          stale at this point and the redundancy audio is not useful, however
537*a58d3d2aSXin Li          the final range is still needed (for testing), so the redundancy is
538*a58d3d2aSXin Li          always decoded but the decoded audio may not be used */
539*a58d3d2aSXin Li       MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
540*a58d3d2aSXin Li       celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
541*a58d3d2aSXin Li                           redundant_audio, F5, NULL, 0);
542*a58d3d2aSXin Li       MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
543*a58d3d2aSXin Li    }
544*a58d3d2aSXin Li 
545*a58d3d2aSXin Li    /* MUST be after PLC */
546*a58d3d2aSXin Li    MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)));
547*a58d3d2aSXin Li 
548*a58d3d2aSXin Li    if (mode != MODE_SILK_ONLY)
549*a58d3d2aSXin Li    {
550*a58d3d2aSXin Li       int celt_frame_size = IMIN(F20, frame_size);
551*a58d3d2aSXin Li       /* Make sure to discard any previous CELT state */
552*a58d3d2aSXin Li       if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
553*a58d3d2aSXin Li          MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
554*a58d3d2aSXin Li       /* Decode CELT */
555*a58d3d2aSXin Li       celt_ret = celt_decode_with_ec_dred(celt_dec, decode_fec ? NULL : data,
556*a58d3d2aSXin Li                                      len, pcm, celt_frame_size, &dec, celt_accum
557*a58d3d2aSXin Li #ifdef ENABLE_DEEP_PLC
558*a58d3d2aSXin Li                                      , &st->lpcnet
559*a58d3d2aSXin Li #endif
560*a58d3d2aSXin Li                                      );
561*a58d3d2aSXin Li    } else {
562*a58d3d2aSXin Li       unsigned char silence[2] = {0xFF, 0xFF};
563*a58d3d2aSXin Li       if (!celt_accum)
564*a58d3d2aSXin Li       {
565*a58d3d2aSXin Li          for (i=0;i<frame_size*st->channels;i++)
566*a58d3d2aSXin Li             pcm[i] = 0;
567*a58d3d2aSXin Li       }
568*a58d3d2aSXin Li       /* For hybrid -> SILK transitions, we let the CELT MDCT
569*a58d3d2aSXin Li          do a fade-out by decoding a silence frame */
570*a58d3d2aSXin Li       if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
571*a58d3d2aSXin Li       {
572*a58d3d2aSXin Li          MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
573*a58d3d2aSXin Li          celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
574*a58d3d2aSXin Li       }
575*a58d3d2aSXin Li    }
576*a58d3d2aSXin Li 
577*a58d3d2aSXin Li    if (mode != MODE_CELT_ONLY && !celt_accum)
578*a58d3d2aSXin Li    {
579*a58d3d2aSXin Li #ifdef FIXED_POINT
580*a58d3d2aSXin Li       for (i=0;i<frame_size*st->channels;i++)
581*a58d3d2aSXin Li          pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i]));
582*a58d3d2aSXin Li #else
583*a58d3d2aSXin Li       for (i=0;i<frame_size*st->channels;i++)
584*a58d3d2aSXin Li          pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]);
585*a58d3d2aSXin Li #endif
586*a58d3d2aSXin Li    }
587*a58d3d2aSXin Li 
588*a58d3d2aSXin Li    {
589*a58d3d2aSXin Li       const CELTMode *celt_mode;
590*a58d3d2aSXin Li       MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)));
591*a58d3d2aSXin Li       window = celt_mode->window;
592*a58d3d2aSXin Li    }
593*a58d3d2aSXin Li 
594*a58d3d2aSXin Li    /* 5 ms redundant frame for SILK->CELT */
595*a58d3d2aSXin Li    if (redundancy && !celt_to_silk)
596*a58d3d2aSXin Li    {
597*a58d3d2aSXin Li       MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
598*a58d3d2aSXin Li       MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
599*a58d3d2aSXin Li 
600*a58d3d2aSXin Li       celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0);
601*a58d3d2aSXin Li       MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)));
602*a58d3d2aSXin Li       smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
603*a58d3d2aSXin Li                   pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
604*a58d3d2aSXin Li    }
605*a58d3d2aSXin Li    /* 5ms redundant frame for CELT->SILK; ignore if the previous frame did not
606*a58d3d2aSXin Li       use CELT (the first redundancy frame in a transition from SILK may have
607*a58d3d2aSXin Li       been lost) */
608*a58d3d2aSXin Li    if (redundancy && celt_to_silk && (st->prev_mode != MODE_SILK_ONLY || st->prev_redundancy))
609*a58d3d2aSXin Li    {
610*a58d3d2aSXin Li       for (c=0;c<st->channels;c++)
611*a58d3d2aSXin Li       {
612*a58d3d2aSXin Li          for (i=0;i<F2_5;i++)
613*a58d3d2aSXin Li             pcm[st->channels*i+c] = redundant_audio[st->channels*i+c];
614*a58d3d2aSXin Li       }
615*a58d3d2aSXin Li       smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5,
616*a58d3d2aSXin Li                   pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs);
617*a58d3d2aSXin Li    }
618*a58d3d2aSXin Li    if (transition)
619*a58d3d2aSXin Li    {
620*a58d3d2aSXin Li       if (audiosize >= F5)
621*a58d3d2aSXin Li       {
622*a58d3d2aSXin Li          for (i=0;i<st->channels*F2_5;i++)
623*a58d3d2aSXin Li             pcm[i] = pcm_transition[i];
624*a58d3d2aSXin Li          smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
625*a58d3d2aSXin Li                      pcm+st->channels*F2_5, F2_5,
626*a58d3d2aSXin Li                      st->channels, window, st->Fs);
627*a58d3d2aSXin Li       } else {
628*a58d3d2aSXin Li          /* Not enough time to do a clean transition, but we do it anyway
629*a58d3d2aSXin Li             This will not preserve amplitude perfectly and may introduce
630*a58d3d2aSXin Li             a bit of temporal aliasing, but it shouldn't be too bad and
631*a58d3d2aSXin Li             that's pretty much the best we can do. In any case, generating this
632*a58d3d2aSXin Li             transition it pretty silly in the first place */
633*a58d3d2aSXin Li          smooth_fade(pcm_transition, pcm,
634*a58d3d2aSXin Li                      pcm, F2_5,
635*a58d3d2aSXin Li                      st->channels, window, st->Fs);
636*a58d3d2aSXin Li       }
637*a58d3d2aSXin Li    }
638*a58d3d2aSXin Li 
639*a58d3d2aSXin Li    if(st->decode_gain)
640*a58d3d2aSXin Li    {
641*a58d3d2aSXin Li       opus_val32 gain;
642*a58d3d2aSXin Li       gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain));
643*a58d3d2aSXin Li       for (i=0;i<frame_size*st->channels;i++)
644*a58d3d2aSXin Li       {
645*a58d3d2aSXin Li          opus_val32 x;
646*a58d3d2aSXin Li          x = MULT16_32_P16(pcm[i],gain);
647*a58d3d2aSXin Li          pcm[i] = SATURATE(x, 32767);
648*a58d3d2aSXin Li       }
649*a58d3d2aSXin Li    }
650*a58d3d2aSXin Li 
651*a58d3d2aSXin Li    if (len <= 1)
652*a58d3d2aSXin Li       st->rangeFinal = 0;
653*a58d3d2aSXin Li    else
654*a58d3d2aSXin Li       st->rangeFinal = dec.rng ^ redundant_rng;
655*a58d3d2aSXin Li 
656*a58d3d2aSXin Li    st->prev_mode = mode;
657*a58d3d2aSXin Li    st->prev_redundancy = redundancy && !celt_to_silk;
658*a58d3d2aSXin Li 
659*a58d3d2aSXin Li    if (celt_ret>=0)
660*a58d3d2aSXin Li    {
661*a58d3d2aSXin Li       if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels))
662*a58d3d2aSXin Li          OPUS_PRINT_INT(audiosize);
663*a58d3d2aSXin Li    }
664*a58d3d2aSXin Li 
665*a58d3d2aSXin Li    RESTORE_STACK;
666*a58d3d2aSXin Li    return celt_ret < 0 ? celt_ret : audiosize;
667*a58d3d2aSXin Li 
668*a58d3d2aSXin Li }
669*a58d3d2aSXin Li 
opus_decode_native(OpusDecoder * st,const unsigned char * data,opus_int32 len,opus_val16 * pcm,int frame_size,int decode_fec,int self_delimited,opus_int32 * packet_offset,int soft_clip,const OpusDRED * dred,opus_int32 dred_offset)670*a58d3d2aSXin Li int opus_decode_native(OpusDecoder *st, const unsigned char *data,
671*a58d3d2aSXin Li       opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec,
672*a58d3d2aSXin Li       int self_delimited, opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset)
673*a58d3d2aSXin Li {
674*a58d3d2aSXin Li    int i, nb_samples;
675*a58d3d2aSXin Li    int count, offset;
676*a58d3d2aSXin Li    unsigned char toc;
677*a58d3d2aSXin Li    int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
678*a58d3d2aSXin Li    /* 48 x 2.5 ms = 120 ms */
679*a58d3d2aSXin Li    opus_int16 size[48];
680*a58d3d2aSXin Li    VALIDATE_OPUS_DECODER(st);
681*a58d3d2aSXin Li    if (decode_fec<0 || decode_fec>1)
682*a58d3d2aSXin Li       return OPUS_BAD_ARG;
683*a58d3d2aSXin Li    /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
684*a58d3d2aSXin Li    if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0)
685*a58d3d2aSXin Li       return OPUS_BAD_ARG;
686*a58d3d2aSXin Li #ifdef ENABLE_DRED
687*a58d3d2aSXin Li    if (dred != NULL && dred->process_stage == 2) {
688*a58d3d2aSXin Li       int F10;
689*a58d3d2aSXin Li       int features_per_frame;
690*a58d3d2aSXin Li       int needed_feature_frames;
691*a58d3d2aSXin Li       int init_frames;
692*a58d3d2aSXin Li       lpcnet_plc_fec_clear(&st->lpcnet);
693*a58d3d2aSXin Li       F10 = st->Fs/100;
694*a58d3d2aSXin Li       /* if blend==0, the last PLC call was "update" and we need to feed two extra 10-ms frames. */
695*a58d3d2aSXin Li       init_frames = (st->lpcnet.blend == 0) ? 2 : 0;
696*a58d3d2aSXin Li       features_per_frame = IMAX(1, frame_size/F10);
697*a58d3d2aSXin Li       needed_feature_frames = init_frames + features_per_frame;
698*a58d3d2aSXin Li       lpcnet_plc_fec_clear(&st->lpcnet);
699*a58d3d2aSXin Li       for (i=0;i<needed_feature_frames;i++) {
700*a58d3d2aSXin Li          int feature_offset;
701*a58d3d2aSXin Li          /* We floor instead of rounding because 5-ms overlap compensates for the missing 0.5 rounding offset. */
702*a58d3d2aSXin Li          feature_offset = init_frames - i - 2 + (int)floor(((float)dred_offset + dred->dred_offset*F10/4)/F10);
703*a58d3d2aSXin Li          if (feature_offset <= 4*dred->nb_latents-1 && feature_offset >= 0) {
704*a58d3d2aSXin Li            lpcnet_plc_fec_add(&st->lpcnet, dred->fec_features+feature_offset*DRED_NUM_FEATURES);
705*a58d3d2aSXin Li          } else {
706*a58d3d2aSXin Li            if (feature_offset >= 0) lpcnet_plc_fec_add(&st->lpcnet, NULL);
707*a58d3d2aSXin Li          }
708*a58d3d2aSXin Li 
709*a58d3d2aSXin Li       }
710*a58d3d2aSXin Li    }
711*a58d3d2aSXin Li #else
712*a58d3d2aSXin Li    (void)dred;
713*a58d3d2aSXin Li    (void)dred_offset;
714*a58d3d2aSXin Li #endif
715*a58d3d2aSXin Li    if (len==0 || data==NULL)
716*a58d3d2aSXin Li    {
717*a58d3d2aSXin Li       int pcm_count=0;
718*a58d3d2aSXin Li       do {
719*a58d3d2aSXin Li          int ret;
720*a58d3d2aSXin Li          ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0);
721*a58d3d2aSXin Li          if (ret<0)
722*a58d3d2aSXin Li             return ret;
723*a58d3d2aSXin Li          pcm_count += ret;
724*a58d3d2aSXin Li       } while (pcm_count < frame_size);
725*a58d3d2aSXin Li       celt_assert(pcm_count == frame_size);
726*a58d3d2aSXin Li       if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels))
727*a58d3d2aSXin Li          OPUS_PRINT_INT(pcm_count);
728*a58d3d2aSXin Li       st->last_packet_duration = pcm_count;
729*a58d3d2aSXin Li       return pcm_count;
730*a58d3d2aSXin Li    } else if (len<0)
731*a58d3d2aSXin Li       return OPUS_BAD_ARG;
732*a58d3d2aSXin Li 
733*a58d3d2aSXin Li    packet_mode = opus_packet_get_mode(data);
734*a58d3d2aSXin Li    packet_bandwidth = opus_packet_get_bandwidth(data);
735*a58d3d2aSXin Li    packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
736*a58d3d2aSXin Li    packet_stream_channels = opus_packet_get_nb_channels(data);
737*a58d3d2aSXin Li 
738*a58d3d2aSXin Li    count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
739*a58d3d2aSXin Li                                   size, &offset, packet_offset, NULL, NULL);
740*a58d3d2aSXin Li    if (count<0)
741*a58d3d2aSXin Li       return count;
742*a58d3d2aSXin Li 
743*a58d3d2aSXin Li    data += offset;
744*a58d3d2aSXin Li 
745*a58d3d2aSXin Li    if (decode_fec)
746*a58d3d2aSXin Li    {
747*a58d3d2aSXin Li       int duration_copy;
748*a58d3d2aSXin Li       int ret;
749*a58d3d2aSXin Li       /* If no FEC can be present, run the PLC (recursive call) */
750*a58d3d2aSXin Li       if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)
751*a58d3d2aSXin Li          return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip, NULL, 0);
752*a58d3d2aSXin Li       /* Otherwise, run the PLC on everything except the size for which we might have FEC */
753*a58d3d2aSXin Li       duration_copy = st->last_packet_duration;
754*a58d3d2aSXin Li       if (frame_size-packet_frame_size!=0)
755*a58d3d2aSXin Li       {
756*a58d3d2aSXin Li          ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip, NULL, 0);
757*a58d3d2aSXin Li          if (ret<0)
758*a58d3d2aSXin Li          {
759*a58d3d2aSXin Li             st->last_packet_duration = duration_copy;
760*a58d3d2aSXin Li             return ret;
761*a58d3d2aSXin Li          }
762*a58d3d2aSXin Li          celt_assert(ret==frame_size-packet_frame_size);
763*a58d3d2aSXin Li       }
764*a58d3d2aSXin Li       /* Complete with FEC */
765*a58d3d2aSXin Li       st->mode = packet_mode;
766*a58d3d2aSXin Li       st->bandwidth = packet_bandwidth;
767*a58d3d2aSXin Li       st->frame_size = packet_frame_size;
768*a58d3d2aSXin Li       st->stream_channels = packet_stream_channels;
769*a58d3d2aSXin Li       ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size),
770*a58d3d2aSXin Li             packet_frame_size, 1);
771*a58d3d2aSXin Li       if (ret<0)
772*a58d3d2aSXin Li          return ret;
773*a58d3d2aSXin Li       else {
774*a58d3d2aSXin Li          if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels))
775*a58d3d2aSXin Li             OPUS_PRINT_INT(frame_size);
776*a58d3d2aSXin Li          st->last_packet_duration = frame_size;
777*a58d3d2aSXin Li          return frame_size;
778*a58d3d2aSXin Li       }
779*a58d3d2aSXin Li    }
780*a58d3d2aSXin Li 
781*a58d3d2aSXin Li    if (count*packet_frame_size > frame_size)
782*a58d3d2aSXin Li       return OPUS_BUFFER_TOO_SMALL;
783*a58d3d2aSXin Li 
784*a58d3d2aSXin Li    /* Update the state as the last step to avoid updating it on an invalid packet */
785*a58d3d2aSXin Li    st->mode = packet_mode;
786*a58d3d2aSXin Li    st->bandwidth = packet_bandwidth;
787*a58d3d2aSXin Li    st->frame_size = packet_frame_size;
788*a58d3d2aSXin Li    st->stream_channels = packet_stream_channels;
789*a58d3d2aSXin Li 
790*a58d3d2aSXin Li    nb_samples=0;
791*a58d3d2aSXin Li    for (i=0;i<count;i++)
792*a58d3d2aSXin Li    {
793*a58d3d2aSXin Li       int ret;
794*a58d3d2aSXin Li       ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0);
795*a58d3d2aSXin Li       if (ret<0)
796*a58d3d2aSXin Li          return ret;
797*a58d3d2aSXin Li       celt_assert(ret==packet_frame_size);
798*a58d3d2aSXin Li       data += size[i];
799*a58d3d2aSXin Li       nb_samples += ret;
800*a58d3d2aSXin Li    }
801*a58d3d2aSXin Li    st->last_packet_duration = nb_samples;
802*a58d3d2aSXin Li    if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels))
803*a58d3d2aSXin Li       OPUS_PRINT_INT(nb_samples);
804*a58d3d2aSXin Li #ifndef FIXED_POINT
805*a58d3d2aSXin Li    if (soft_clip)
806*a58d3d2aSXin Li       opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem);
807*a58d3d2aSXin Li    else
808*a58d3d2aSXin Li       st->softclip_mem[0]=st->softclip_mem[1]=0;
809*a58d3d2aSXin Li #endif
810*a58d3d2aSXin Li    return nb_samples;
811*a58d3d2aSXin Li }
812*a58d3d2aSXin Li 
813*a58d3d2aSXin Li #ifdef FIXED_POINT
814*a58d3d2aSXin Li 
opus_decode(OpusDecoder * st,const unsigned char * data,opus_int32 len,opus_val16 * pcm,int frame_size,int decode_fec)815*a58d3d2aSXin Li int opus_decode(OpusDecoder *st, const unsigned char *data,
816*a58d3d2aSXin Li       opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
817*a58d3d2aSXin Li {
818*a58d3d2aSXin Li    if(frame_size<=0)
819*a58d3d2aSXin Li       return OPUS_BAD_ARG;
820*a58d3d2aSXin Li    return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
821*a58d3d2aSXin Li }
822*a58d3d2aSXin Li 
823*a58d3d2aSXin Li #ifndef DISABLE_FLOAT_API
opus_decode_float(OpusDecoder * st,const unsigned char * data,opus_int32 len,float * pcm,int frame_size,int decode_fec)824*a58d3d2aSXin Li int opus_decode_float(OpusDecoder *st, const unsigned char *data,
825*a58d3d2aSXin Li       opus_int32 len, float *pcm, int frame_size, int decode_fec)
826*a58d3d2aSXin Li {
827*a58d3d2aSXin Li    VARDECL(opus_int16, out);
828*a58d3d2aSXin Li    int ret, i;
829*a58d3d2aSXin Li    int nb_samples;
830*a58d3d2aSXin Li    ALLOC_STACK;
831*a58d3d2aSXin Li 
832*a58d3d2aSXin Li    if(frame_size<=0)
833*a58d3d2aSXin Li    {
834*a58d3d2aSXin Li       RESTORE_STACK;
835*a58d3d2aSXin Li       return OPUS_BAD_ARG;
836*a58d3d2aSXin Li    }
837*a58d3d2aSXin Li    if (data != NULL && len > 0 && !decode_fec)
838*a58d3d2aSXin Li    {
839*a58d3d2aSXin Li       nb_samples = opus_decoder_get_nb_samples(st, data, len);
840*a58d3d2aSXin Li       if (nb_samples>0)
841*a58d3d2aSXin Li          frame_size = IMIN(frame_size, nb_samples);
842*a58d3d2aSXin Li       else
843*a58d3d2aSXin Li          return OPUS_INVALID_PACKET;
844*a58d3d2aSXin Li    }
845*a58d3d2aSXin Li    celt_assert(st->channels == 1 || st->channels == 2);
846*a58d3d2aSXin Li    ALLOC(out, frame_size*st->channels, opus_int16);
847*a58d3d2aSXin Li 
848*a58d3d2aSXin Li    ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
849*a58d3d2aSXin Li    if (ret > 0)
850*a58d3d2aSXin Li    {
851*a58d3d2aSXin Li       for (i=0;i<ret*st->channels;i++)
852*a58d3d2aSXin Li          pcm[i] = (1.f/32768.f)*(out[i]);
853*a58d3d2aSXin Li    }
854*a58d3d2aSXin Li    RESTORE_STACK;
855*a58d3d2aSXin Li    return ret;
856*a58d3d2aSXin Li }
857*a58d3d2aSXin Li #endif
858*a58d3d2aSXin Li 
859*a58d3d2aSXin Li 
860*a58d3d2aSXin Li #else
opus_decode(OpusDecoder * st,const unsigned char * data,opus_int32 len,opus_int16 * pcm,int frame_size,int decode_fec)861*a58d3d2aSXin Li int opus_decode(OpusDecoder *st, const unsigned char *data,
862*a58d3d2aSXin Li       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
863*a58d3d2aSXin Li {
864*a58d3d2aSXin Li    VARDECL(float, out);
865*a58d3d2aSXin Li    int ret, i;
866*a58d3d2aSXin Li    int nb_samples;
867*a58d3d2aSXin Li    ALLOC_STACK;
868*a58d3d2aSXin Li 
869*a58d3d2aSXin Li    if(frame_size<=0)
870*a58d3d2aSXin Li    {
871*a58d3d2aSXin Li       RESTORE_STACK;
872*a58d3d2aSXin Li       return OPUS_BAD_ARG;
873*a58d3d2aSXin Li    }
874*a58d3d2aSXin Li 
875*a58d3d2aSXin Li    if (data != NULL && len > 0 && !decode_fec)
876*a58d3d2aSXin Li    {
877*a58d3d2aSXin Li       nb_samples = opus_decoder_get_nb_samples(st, data, len);
878*a58d3d2aSXin Li       if (nb_samples>0)
879*a58d3d2aSXin Li          frame_size = IMIN(frame_size, nb_samples);
880*a58d3d2aSXin Li       else
881*a58d3d2aSXin Li          return OPUS_INVALID_PACKET;
882*a58d3d2aSXin Li    }
883*a58d3d2aSXin Li    celt_assert(st->channels == 1 || st->channels == 2);
884*a58d3d2aSXin Li    ALLOC(out, frame_size*st->channels, float);
885*a58d3d2aSXin Li 
886*a58d3d2aSXin Li    ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1, NULL, 0);
887*a58d3d2aSXin Li    if (ret > 0)
888*a58d3d2aSXin Li    {
889*a58d3d2aSXin Li       for (i=0;i<ret*st->channels;i++)
890*a58d3d2aSXin Li          pcm[i] = FLOAT2INT16(out[i]);
891*a58d3d2aSXin Li    }
892*a58d3d2aSXin Li    RESTORE_STACK;
893*a58d3d2aSXin Li    return ret;
894*a58d3d2aSXin Li }
895*a58d3d2aSXin Li 
opus_decode_float(OpusDecoder * st,const unsigned char * data,opus_int32 len,opus_val16 * pcm,int frame_size,int decode_fec)896*a58d3d2aSXin Li int opus_decode_float(OpusDecoder *st, const unsigned char *data,
897*a58d3d2aSXin Li       opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
898*a58d3d2aSXin Li {
899*a58d3d2aSXin Li    if(frame_size<=0)
900*a58d3d2aSXin Li       return OPUS_BAD_ARG;
901*a58d3d2aSXin Li    return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
902*a58d3d2aSXin Li }
903*a58d3d2aSXin Li 
904*a58d3d2aSXin Li #endif
905*a58d3d2aSXin Li 
opus_decoder_ctl(OpusDecoder * st,int request,...)906*a58d3d2aSXin Li int opus_decoder_ctl(OpusDecoder *st, int request, ...)
907*a58d3d2aSXin Li {
908*a58d3d2aSXin Li    int ret = OPUS_OK;
909*a58d3d2aSXin Li    va_list ap;
910*a58d3d2aSXin Li    void *silk_dec;
911*a58d3d2aSXin Li    CELTDecoder *celt_dec;
912*a58d3d2aSXin Li 
913*a58d3d2aSXin Li    silk_dec = (char*)st+st->silk_dec_offset;
914*a58d3d2aSXin Li    celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
915*a58d3d2aSXin Li 
916*a58d3d2aSXin Li 
917*a58d3d2aSXin Li    va_start(ap, request);
918*a58d3d2aSXin Li 
919*a58d3d2aSXin Li    switch (request)
920*a58d3d2aSXin Li    {
921*a58d3d2aSXin Li    case OPUS_GET_BANDWIDTH_REQUEST:
922*a58d3d2aSXin Li    {
923*a58d3d2aSXin Li       opus_int32 *value = va_arg(ap, opus_int32*);
924*a58d3d2aSXin Li       if (!value)
925*a58d3d2aSXin Li       {
926*a58d3d2aSXin Li          goto bad_arg;
927*a58d3d2aSXin Li       }
928*a58d3d2aSXin Li       *value = st->bandwidth;
929*a58d3d2aSXin Li    }
930*a58d3d2aSXin Li    break;
931*a58d3d2aSXin Li    case OPUS_SET_COMPLEXITY_REQUEST:
932*a58d3d2aSXin Li    {
933*a58d3d2aSXin Li        opus_int32 value = va_arg(ap, opus_int32);
934*a58d3d2aSXin Li        if(value<0 || value>10)
935*a58d3d2aSXin Li        {
936*a58d3d2aSXin Li           goto bad_arg;
937*a58d3d2aSXin Li        }
938*a58d3d2aSXin Li        st->complexity = value;
939*a58d3d2aSXin Li        celt_decoder_ctl(celt_dec, OPUS_SET_COMPLEXITY(value));
940*a58d3d2aSXin Li    }
941*a58d3d2aSXin Li    break;
942*a58d3d2aSXin Li    case OPUS_GET_COMPLEXITY_REQUEST:
943*a58d3d2aSXin Li    {
944*a58d3d2aSXin Li        opus_int32 *value = va_arg(ap, opus_int32*);
945*a58d3d2aSXin Li        if (!value)
946*a58d3d2aSXin Li        {
947*a58d3d2aSXin Li           goto bad_arg;
948*a58d3d2aSXin Li        }
949*a58d3d2aSXin Li        *value = st->complexity;
950*a58d3d2aSXin Li    }
951*a58d3d2aSXin Li    break;
952*a58d3d2aSXin Li    case OPUS_GET_FINAL_RANGE_REQUEST:
953*a58d3d2aSXin Li    {
954*a58d3d2aSXin Li       opus_uint32 *value = va_arg(ap, opus_uint32*);
955*a58d3d2aSXin Li       if (!value)
956*a58d3d2aSXin Li       {
957*a58d3d2aSXin Li          goto bad_arg;
958*a58d3d2aSXin Li       }
959*a58d3d2aSXin Li       *value = st->rangeFinal;
960*a58d3d2aSXin Li    }
961*a58d3d2aSXin Li    break;
962*a58d3d2aSXin Li    case OPUS_RESET_STATE:
963*a58d3d2aSXin Li    {
964*a58d3d2aSXin Li       OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
965*a58d3d2aSXin Li             sizeof(OpusDecoder)-
966*a58d3d2aSXin Li             ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));
967*a58d3d2aSXin Li 
968*a58d3d2aSXin Li       celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
969*a58d3d2aSXin Li       silk_ResetDecoder( silk_dec );
970*a58d3d2aSXin Li       st->stream_channels = st->channels;
971*a58d3d2aSXin Li       st->frame_size = st->Fs/400;
972*a58d3d2aSXin Li #ifdef ENABLE_DEEP_PLC
973*a58d3d2aSXin Li       lpcnet_plc_reset( &st->lpcnet );
974*a58d3d2aSXin Li #endif
975*a58d3d2aSXin Li    }
976*a58d3d2aSXin Li    break;
977*a58d3d2aSXin Li    case OPUS_GET_SAMPLE_RATE_REQUEST:
978*a58d3d2aSXin Li    {
979*a58d3d2aSXin Li       opus_int32 *value = va_arg(ap, opus_int32*);
980*a58d3d2aSXin Li       if (!value)
981*a58d3d2aSXin Li       {
982*a58d3d2aSXin Li          goto bad_arg;
983*a58d3d2aSXin Li       }
984*a58d3d2aSXin Li       *value = st->Fs;
985*a58d3d2aSXin Li    }
986*a58d3d2aSXin Li    break;
987*a58d3d2aSXin Li    case OPUS_GET_PITCH_REQUEST:
988*a58d3d2aSXin Li    {
989*a58d3d2aSXin Li       opus_int32 *value = va_arg(ap, opus_int32*);
990*a58d3d2aSXin Li       if (!value)
991*a58d3d2aSXin Li       {
992*a58d3d2aSXin Li          goto bad_arg;
993*a58d3d2aSXin Li       }
994*a58d3d2aSXin Li       if (st->prev_mode == MODE_CELT_ONLY)
995*a58d3d2aSXin Li          ret = celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
996*a58d3d2aSXin Li       else
997*a58d3d2aSXin Li          *value = st->DecControl.prevPitchLag;
998*a58d3d2aSXin Li    }
999*a58d3d2aSXin Li    break;
1000*a58d3d2aSXin Li    case OPUS_GET_GAIN_REQUEST:
1001*a58d3d2aSXin Li    {
1002*a58d3d2aSXin Li       opus_int32 *value = va_arg(ap, opus_int32*);
1003*a58d3d2aSXin Li       if (!value)
1004*a58d3d2aSXin Li       {
1005*a58d3d2aSXin Li          goto bad_arg;
1006*a58d3d2aSXin Li       }
1007*a58d3d2aSXin Li       *value = st->decode_gain;
1008*a58d3d2aSXin Li    }
1009*a58d3d2aSXin Li    break;
1010*a58d3d2aSXin Li    case OPUS_SET_GAIN_REQUEST:
1011*a58d3d2aSXin Li    {
1012*a58d3d2aSXin Li        opus_int32 value = va_arg(ap, opus_int32);
1013*a58d3d2aSXin Li        if (value<-32768 || value>32767)
1014*a58d3d2aSXin Li        {
1015*a58d3d2aSXin Li           goto bad_arg;
1016*a58d3d2aSXin Li        }
1017*a58d3d2aSXin Li        st->decode_gain = value;
1018*a58d3d2aSXin Li    }
1019*a58d3d2aSXin Li    break;
1020*a58d3d2aSXin Li    case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
1021*a58d3d2aSXin Li    {
1022*a58d3d2aSXin Li       opus_int32 *value = va_arg(ap, opus_int32*);
1023*a58d3d2aSXin Li       if (!value)
1024*a58d3d2aSXin Li       {
1025*a58d3d2aSXin Li          goto bad_arg;
1026*a58d3d2aSXin Li       }
1027*a58d3d2aSXin Li       *value = st->last_packet_duration;
1028*a58d3d2aSXin Li    }
1029*a58d3d2aSXin Li    break;
1030*a58d3d2aSXin Li    case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
1031*a58d3d2aSXin Li    {
1032*a58d3d2aSXin Li        opus_int32 value = va_arg(ap, opus_int32);
1033*a58d3d2aSXin Li        if(value<0 || value>1)
1034*a58d3d2aSXin Li        {
1035*a58d3d2aSXin Li           goto bad_arg;
1036*a58d3d2aSXin Li        }
1037*a58d3d2aSXin Li        ret = celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
1038*a58d3d2aSXin Li    }
1039*a58d3d2aSXin Li    break;
1040*a58d3d2aSXin Li    case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
1041*a58d3d2aSXin Li    {
1042*a58d3d2aSXin Li        opus_int32 *value = va_arg(ap, opus_int32*);
1043*a58d3d2aSXin Li        if (!value)
1044*a58d3d2aSXin Li        {
1045*a58d3d2aSXin Li           goto bad_arg;
1046*a58d3d2aSXin Li        }
1047*a58d3d2aSXin Li        ret = celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
1048*a58d3d2aSXin Li    }
1049*a58d3d2aSXin Li    break;
1050*a58d3d2aSXin Li #ifdef USE_WEIGHTS_FILE
1051*a58d3d2aSXin Li    case OPUS_SET_DNN_BLOB_REQUEST:
1052*a58d3d2aSXin Li    {
1053*a58d3d2aSXin Li        const unsigned char *data = va_arg(ap, const unsigned char *);
1054*a58d3d2aSXin Li        opus_int32 len = va_arg(ap, opus_int32);
1055*a58d3d2aSXin Li        if(len<0 || data == NULL)
1056*a58d3d2aSXin Li        {
1057*a58d3d2aSXin Li           goto bad_arg;
1058*a58d3d2aSXin Li        }
1059*a58d3d2aSXin Li        ret = lpcnet_plc_load_model(&st->lpcnet, data, len);
1060*a58d3d2aSXin Li        ret = silk_LoadOSCEModels(silk_dec, data, len) || ret;
1061*a58d3d2aSXin Li    }
1062*a58d3d2aSXin Li    break;
1063*a58d3d2aSXin Li #endif
1064*a58d3d2aSXin Li    default:
1065*a58d3d2aSXin Li       /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
1066*a58d3d2aSXin Li       ret = OPUS_UNIMPLEMENTED;
1067*a58d3d2aSXin Li       break;
1068*a58d3d2aSXin Li    }
1069*a58d3d2aSXin Li 
1070*a58d3d2aSXin Li    va_end(ap);
1071*a58d3d2aSXin Li    return ret;
1072*a58d3d2aSXin Li bad_arg:
1073*a58d3d2aSXin Li    va_end(ap);
1074*a58d3d2aSXin Li    return OPUS_BAD_ARG;
1075*a58d3d2aSXin Li }
1076*a58d3d2aSXin Li 
opus_decoder_destroy(OpusDecoder * st)1077*a58d3d2aSXin Li void opus_decoder_destroy(OpusDecoder *st)
1078*a58d3d2aSXin Li {
1079*a58d3d2aSXin Li    opus_free(st);
1080*a58d3d2aSXin Li }
1081*a58d3d2aSXin Li 
1082*a58d3d2aSXin Li 
opus_packet_get_bandwidth(const unsigned char * data)1083*a58d3d2aSXin Li int opus_packet_get_bandwidth(const unsigned char *data)
1084*a58d3d2aSXin Li {
1085*a58d3d2aSXin Li    int bandwidth;
1086*a58d3d2aSXin Li    if (data[0]&0x80)
1087*a58d3d2aSXin Li    {
1088*a58d3d2aSXin Li       bandwidth = OPUS_BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3);
1089*a58d3d2aSXin Li       if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
1090*a58d3d2aSXin Li          bandwidth = OPUS_BANDWIDTH_NARROWBAND;
1091*a58d3d2aSXin Li    } else if ((data[0]&0x60) == 0x60)
1092*a58d3d2aSXin Li    {
1093*a58d3d2aSXin Li       bandwidth = (data[0]&0x10) ? OPUS_BANDWIDTH_FULLBAND :
1094*a58d3d2aSXin Li                                    OPUS_BANDWIDTH_SUPERWIDEBAND;
1095*a58d3d2aSXin Li    } else {
1096*a58d3d2aSXin Li       bandwidth = OPUS_BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3);
1097*a58d3d2aSXin Li    }
1098*a58d3d2aSXin Li    return bandwidth;
1099*a58d3d2aSXin Li }
1100*a58d3d2aSXin Li 
opus_packet_get_nb_channels(const unsigned char * data)1101*a58d3d2aSXin Li int opus_packet_get_nb_channels(const unsigned char *data)
1102*a58d3d2aSXin Li {
1103*a58d3d2aSXin Li    return (data[0]&0x4) ? 2 : 1;
1104*a58d3d2aSXin Li }
1105*a58d3d2aSXin Li 
opus_packet_get_nb_frames(const unsigned char packet[],opus_int32 len)1106*a58d3d2aSXin Li int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len)
1107*a58d3d2aSXin Li {
1108*a58d3d2aSXin Li    int count;
1109*a58d3d2aSXin Li    if (len<1)
1110*a58d3d2aSXin Li       return OPUS_BAD_ARG;
1111*a58d3d2aSXin Li    count = packet[0]&0x3;
1112*a58d3d2aSXin Li    if (count==0)
1113*a58d3d2aSXin Li       return 1;
1114*a58d3d2aSXin Li    else if (count!=3)
1115*a58d3d2aSXin Li       return 2;
1116*a58d3d2aSXin Li    else if (len<2)
1117*a58d3d2aSXin Li       return OPUS_INVALID_PACKET;
1118*a58d3d2aSXin Li    else
1119*a58d3d2aSXin Li       return packet[1]&0x3F;
1120*a58d3d2aSXin Li }
1121*a58d3d2aSXin Li 
opus_packet_get_nb_samples(const unsigned char packet[],opus_int32 len,opus_int32 Fs)1122*a58d3d2aSXin Li int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len,
1123*a58d3d2aSXin Li       opus_int32 Fs)
1124*a58d3d2aSXin Li {
1125*a58d3d2aSXin Li    int samples;
1126*a58d3d2aSXin Li    int count = opus_packet_get_nb_frames(packet, len);
1127*a58d3d2aSXin Li 
1128*a58d3d2aSXin Li    if (count<0)
1129*a58d3d2aSXin Li       return count;
1130*a58d3d2aSXin Li 
1131*a58d3d2aSXin Li    samples = count*opus_packet_get_samples_per_frame(packet, Fs);
1132*a58d3d2aSXin Li    /* Can't have more than 120 ms */
1133*a58d3d2aSXin Li    if (samples*25 > Fs*3)
1134*a58d3d2aSXin Li       return OPUS_INVALID_PACKET;
1135*a58d3d2aSXin Li    else
1136*a58d3d2aSXin Li       return samples;
1137*a58d3d2aSXin Li }
1138*a58d3d2aSXin Li 
opus_packet_has_lbrr(const unsigned char packet[],opus_int32 len)1139*a58d3d2aSXin Li int opus_packet_has_lbrr(const unsigned char packet[], opus_int32 len)
1140*a58d3d2aSXin Li {
1141*a58d3d2aSXin Li    int ret;
1142*a58d3d2aSXin Li    const unsigned char *frames[48];
1143*a58d3d2aSXin Li    opus_int16 size[48];
1144*a58d3d2aSXin Li    int packet_mode, packet_frame_size, packet_stream_channels;
1145*a58d3d2aSXin Li    int nb_frames=1;
1146*a58d3d2aSXin Li    int lbrr;
1147*a58d3d2aSXin Li 
1148*a58d3d2aSXin Li    packet_mode = opus_packet_get_mode(packet);
1149*a58d3d2aSXin Li    if (packet_mode == MODE_CELT_ONLY)
1150*a58d3d2aSXin Li       return 0;
1151*a58d3d2aSXin Li    packet_frame_size = opus_packet_get_samples_per_frame(packet, 48000);
1152*a58d3d2aSXin Li    if (packet_frame_size > 960)
1153*a58d3d2aSXin Li       nb_frames = packet_frame_size/960;
1154*a58d3d2aSXin Li    packet_stream_channels = opus_packet_get_nb_channels(packet);
1155*a58d3d2aSXin Li    ret = opus_packet_parse(packet, len, NULL, frames, size, NULL);
1156*a58d3d2aSXin Li    if (ret <= 0)
1157*a58d3d2aSXin Li       return ret;
1158*a58d3d2aSXin Li    lbrr = (frames[0][0] >> (7-nb_frames)) & 0x1;
1159*a58d3d2aSXin Li    if (packet_stream_channels == 2)
1160*a58d3d2aSXin Li       lbrr = lbrr || ((frames[0][0] >> (6-2*nb_frames)) & 0x1);
1161*a58d3d2aSXin Li    return lbrr;
1162*a58d3d2aSXin Li }
1163*a58d3d2aSXin Li 
opus_decoder_get_nb_samples(const OpusDecoder * dec,const unsigned char packet[],opus_int32 len)1164*a58d3d2aSXin Li int opus_decoder_get_nb_samples(const OpusDecoder *dec,
1165*a58d3d2aSXin Li       const unsigned char packet[], opus_int32 len)
1166*a58d3d2aSXin Li {
1167*a58d3d2aSXin Li    return opus_packet_get_nb_samples(packet, len, dec->Fs);
1168*a58d3d2aSXin Li }
1169*a58d3d2aSXin Li 
1170*a58d3d2aSXin Li struct OpusDREDDecoder {
1171*a58d3d2aSXin Li #ifdef ENABLE_DRED
1172*a58d3d2aSXin Li    RDOVAEDec model;
1173*a58d3d2aSXin Li #endif
1174*a58d3d2aSXin Li    int loaded;
1175*a58d3d2aSXin Li    int arch;
1176*a58d3d2aSXin Li    opus_uint32 magic;
1177*a58d3d2aSXin Li };
1178*a58d3d2aSXin Li 
1179*a58d3d2aSXin Li #if defined(ENABLE_DRED) && (defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS))
validate_dred_decoder(OpusDREDDecoder * st)1180*a58d3d2aSXin Li static void validate_dred_decoder(OpusDREDDecoder *st)
1181*a58d3d2aSXin Li {
1182*a58d3d2aSXin Li    celt_assert(st->magic == 0xD8EDDEC0);
1183*a58d3d2aSXin Li #ifdef OPUS_ARCHMASK
1184*a58d3d2aSXin Li    celt_assert(st->arch >= 0);
1185*a58d3d2aSXin Li    celt_assert(st->arch <= OPUS_ARCHMASK);
1186*a58d3d2aSXin Li #endif
1187*a58d3d2aSXin Li }
1188*a58d3d2aSXin Li #define VALIDATE_DRED_DECODER(st) validate_dred_decoder(st)
1189*a58d3d2aSXin Li #else
1190*a58d3d2aSXin Li #define VALIDATE_DRED_DECODER(st)
1191*a58d3d2aSXin Li #endif
1192*a58d3d2aSXin Li 
1193*a58d3d2aSXin Li 
opus_dred_decoder_get_size(void)1194*a58d3d2aSXin Li int opus_dred_decoder_get_size(void)
1195*a58d3d2aSXin Li {
1196*a58d3d2aSXin Li   return sizeof(OpusDREDDecoder);
1197*a58d3d2aSXin Li }
1198*a58d3d2aSXin Li 
1199*a58d3d2aSXin Li #ifdef ENABLE_DRED
dred_decoder_load_model(OpusDREDDecoder * dec,const unsigned char * data,int len)1200*a58d3d2aSXin Li int dred_decoder_load_model(OpusDREDDecoder *dec, const unsigned char *data, int len)
1201*a58d3d2aSXin Li {
1202*a58d3d2aSXin Li     WeightArray *list;
1203*a58d3d2aSXin Li     int ret;
1204*a58d3d2aSXin Li     parse_weights(&list, data, len);
1205*a58d3d2aSXin Li     ret = init_rdovaedec(&dec->model, list);
1206*a58d3d2aSXin Li     opus_free(list);
1207*a58d3d2aSXin Li     if (ret == 0) dec->loaded = 1;
1208*a58d3d2aSXin Li     return (ret == 0) ? OPUS_OK : OPUS_BAD_ARG;
1209*a58d3d2aSXin Li }
1210*a58d3d2aSXin Li #endif
1211*a58d3d2aSXin Li 
opus_dred_decoder_init(OpusDREDDecoder * dec)1212*a58d3d2aSXin Li int opus_dred_decoder_init(OpusDREDDecoder *dec)
1213*a58d3d2aSXin Li {
1214*a58d3d2aSXin Li    int ret = 0;
1215*a58d3d2aSXin Li    dec->loaded = 0;
1216*a58d3d2aSXin Li #if defined(ENABLE_DRED) && !defined(USE_WEIGHTS_FILE)
1217*a58d3d2aSXin Li    ret = init_rdovaedec(&dec->model, rdovaedec_arrays);
1218*a58d3d2aSXin Li    if (ret == 0) dec->loaded = 1;
1219*a58d3d2aSXin Li #endif
1220*a58d3d2aSXin Li    dec->arch = opus_select_arch();
1221*a58d3d2aSXin Li    /* To make sure nobody forgets to init, use a magic number. */
1222*a58d3d2aSXin Li    dec->magic = 0xD8EDDEC0;
1223*a58d3d2aSXin Li    return (ret == 0) ? OPUS_OK : OPUS_UNIMPLEMENTED;
1224*a58d3d2aSXin Li }
1225*a58d3d2aSXin Li 
opus_dred_decoder_create(int * error)1226*a58d3d2aSXin Li OpusDREDDecoder *opus_dred_decoder_create(int *error)
1227*a58d3d2aSXin Li {
1228*a58d3d2aSXin Li    int ret;
1229*a58d3d2aSXin Li    OpusDREDDecoder *dec;
1230*a58d3d2aSXin Li    dec = (OpusDREDDecoder *)opus_alloc(opus_dred_decoder_get_size());
1231*a58d3d2aSXin Li    if (dec == NULL)
1232*a58d3d2aSXin Li    {
1233*a58d3d2aSXin Li       if (error)
1234*a58d3d2aSXin Li          *error = OPUS_ALLOC_FAIL;
1235*a58d3d2aSXin Li       return NULL;
1236*a58d3d2aSXin Li    }
1237*a58d3d2aSXin Li    ret = opus_dred_decoder_init(dec);
1238*a58d3d2aSXin Li    if (error)
1239*a58d3d2aSXin Li       *error = ret;
1240*a58d3d2aSXin Li    if (ret != OPUS_OK)
1241*a58d3d2aSXin Li    {
1242*a58d3d2aSXin Li       opus_free(dec);
1243*a58d3d2aSXin Li       dec = NULL;
1244*a58d3d2aSXin Li    }
1245*a58d3d2aSXin Li    return dec;
1246*a58d3d2aSXin Li }
1247*a58d3d2aSXin Li 
opus_dred_decoder_destroy(OpusDREDDecoder * dec)1248*a58d3d2aSXin Li void opus_dred_decoder_destroy(OpusDREDDecoder *dec)
1249*a58d3d2aSXin Li {
1250*a58d3d2aSXin Li    if (dec) dec->magic = 0xDE57801D;
1251*a58d3d2aSXin Li    opus_free(dec);
1252*a58d3d2aSXin Li }
1253*a58d3d2aSXin Li 
opus_dred_decoder_ctl(OpusDREDDecoder * dred_dec,int request,...)1254*a58d3d2aSXin Li int opus_dred_decoder_ctl(OpusDREDDecoder *dred_dec, int request, ...)
1255*a58d3d2aSXin Li {
1256*a58d3d2aSXin Li #ifdef ENABLE_DRED
1257*a58d3d2aSXin Li    int ret = OPUS_OK;
1258*a58d3d2aSXin Li    va_list ap;
1259*a58d3d2aSXin Li 
1260*a58d3d2aSXin Li    va_start(ap, request);
1261*a58d3d2aSXin Li    (void)dred_dec;
1262*a58d3d2aSXin Li    switch (request)
1263*a58d3d2aSXin Li    {
1264*a58d3d2aSXin Li # ifdef USE_WEIGHTS_FILE
1265*a58d3d2aSXin Li    case OPUS_SET_DNN_BLOB_REQUEST:
1266*a58d3d2aSXin Li    {
1267*a58d3d2aSXin Li       const unsigned char *data = va_arg(ap, const unsigned char *);
1268*a58d3d2aSXin Li       opus_int32 len = va_arg(ap, opus_int32);
1269*a58d3d2aSXin Li       if(len<0 || data == NULL)
1270*a58d3d2aSXin Li       {
1271*a58d3d2aSXin Li          goto bad_arg;
1272*a58d3d2aSXin Li       }
1273*a58d3d2aSXin Li       return dred_decoder_load_model(dred_dec, data, len);
1274*a58d3d2aSXin Li    }
1275*a58d3d2aSXin Li    break;
1276*a58d3d2aSXin Li # endif
1277*a58d3d2aSXin Li    default:
1278*a58d3d2aSXin Li      /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
1279*a58d3d2aSXin Li      ret = OPUS_UNIMPLEMENTED;
1280*a58d3d2aSXin Li      break;
1281*a58d3d2aSXin Li   }
1282*a58d3d2aSXin Li   va_end(ap);
1283*a58d3d2aSXin Li   return ret;
1284*a58d3d2aSXin Li # ifdef USE_WEIGHTS_FILE
1285*a58d3d2aSXin Li bad_arg:
1286*a58d3d2aSXin Li   va_end(ap);
1287*a58d3d2aSXin Li   return OPUS_BAD_ARG;
1288*a58d3d2aSXin Li # endif
1289*a58d3d2aSXin Li #else
1290*a58d3d2aSXin Li   (void)dred_dec;
1291*a58d3d2aSXin Li   (void)request;
1292*a58d3d2aSXin Li   return OPUS_UNIMPLEMENTED;
1293*a58d3d2aSXin Li #endif
1294*a58d3d2aSXin Li }
1295*a58d3d2aSXin Li 
1296*a58d3d2aSXin Li #ifdef ENABLE_DRED
dred_find_payload(const unsigned char * data,opus_int32 len,const unsigned char ** payload,int * dred_frame_offset)1297*a58d3d2aSXin Li static int dred_find_payload(const unsigned char *data, opus_int32 len, const unsigned char **payload, int *dred_frame_offset)
1298*a58d3d2aSXin Li {
1299*a58d3d2aSXin Li    const unsigned char *data0;
1300*a58d3d2aSXin Li    int len0;
1301*a58d3d2aSXin Li    int frame = 0;
1302*a58d3d2aSXin Li    int ret;
1303*a58d3d2aSXin Li    const unsigned char *frames[48];
1304*a58d3d2aSXin Li    opus_int16 size[48];
1305*a58d3d2aSXin Li    int frame_size;
1306*a58d3d2aSXin Li 
1307*a58d3d2aSXin Li    *payload = NULL;
1308*a58d3d2aSXin Li    /* Get the padding section of the packet. */
1309*a58d3d2aSXin Li    ret = opus_packet_parse_impl(data, len, 0, NULL, frames, size, NULL, NULL, &data0, &len0);
1310*a58d3d2aSXin Li    if (ret < 0)
1311*a58d3d2aSXin Li       return ret;
1312*a58d3d2aSXin Li    frame_size = opus_packet_get_samples_per_frame(data, 48000);
1313*a58d3d2aSXin Li    data = data0;
1314*a58d3d2aSXin Li    len = len0;
1315*a58d3d2aSXin Li    /* Scan extensions in order until we find the earliest frame with DRED data. */
1316*a58d3d2aSXin Li    while (len > 0)
1317*a58d3d2aSXin Li    {
1318*a58d3d2aSXin Li       opus_int32 header_size;
1319*a58d3d2aSXin Li       int id, L;
1320*a58d3d2aSXin Li       len0 = len;
1321*a58d3d2aSXin Li       data0 = data;
1322*a58d3d2aSXin Li       id = *data0 >> 1;
1323*a58d3d2aSXin Li       L = *data0 & 0x1;
1324*a58d3d2aSXin Li       len = skip_extension(&data, len, &header_size);
1325*a58d3d2aSXin Li       if (len < 0)
1326*a58d3d2aSXin Li          break;
1327*a58d3d2aSXin Li       if (id == 1)
1328*a58d3d2aSXin Li       {
1329*a58d3d2aSXin Li          if (L==0)
1330*a58d3d2aSXin Li          {
1331*a58d3d2aSXin Li             frame++;
1332*a58d3d2aSXin Li          } else {
1333*a58d3d2aSXin Li             frame += data0[1];
1334*a58d3d2aSXin Li          }
1335*a58d3d2aSXin Li       } else if (id == DRED_EXTENSION_ID)
1336*a58d3d2aSXin Li       {
1337*a58d3d2aSXin Li          const unsigned char *curr_payload;
1338*a58d3d2aSXin Li          opus_int32 curr_payload_len;
1339*a58d3d2aSXin Li          curr_payload = data0+header_size;
1340*a58d3d2aSXin Li          curr_payload_len = (data-data0)-header_size;
1341*a58d3d2aSXin Li          /* DRED position in the packet, in units of 2.5 ms like for the signaled DRED offset. */
1342*a58d3d2aSXin Li          *dred_frame_offset = frame*frame_size/120;
1343*a58d3d2aSXin Li #ifdef DRED_EXPERIMENTAL_VERSION
1344*a58d3d2aSXin Li          /* Check that temporary extension type and version match.
1345*a58d3d2aSXin Li             This check will be removed once extension is finalized. */
1346*a58d3d2aSXin Li          if (curr_payload_len > DRED_EXPERIMENTAL_BYTES && curr_payload[0] == 'D' && curr_payload[1] == DRED_EXPERIMENTAL_VERSION) {
1347*a58d3d2aSXin Li             *payload = curr_payload+2;
1348*a58d3d2aSXin Li             return curr_payload_len-2;
1349*a58d3d2aSXin Li          }
1350*a58d3d2aSXin Li #else
1351*a58d3d2aSXin Li          if (curr_payload_len > 0) {
1352*a58d3d2aSXin Li             *payload = curr_payload;
1353*a58d3d2aSXin Li             return curr_payload_len;
1354*a58d3d2aSXin Li          }
1355*a58d3d2aSXin Li #endif
1356*a58d3d2aSXin Li       }
1357*a58d3d2aSXin Li    }
1358*a58d3d2aSXin Li    return 0;
1359*a58d3d2aSXin Li }
1360*a58d3d2aSXin Li #endif
1361*a58d3d2aSXin Li 
opus_dred_get_size(void)1362*a58d3d2aSXin Li int opus_dred_get_size(void)
1363*a58d3d2aSXin Li {
1364*a58d3d2aSXin Li #ifdef ENABLE_DRED
1365*a58d3d2aSXin Li   return sizeof(OpusDRED);
1366*a58d3d2aSXin Li #else
1367*a58d3d2aSXin Li   return 0;
1368*a58d3d2aSXin Li #endif
1369*a58d3d2aSXin Li }
1370*a58d3d2aSXin Li 
opus_dred_alloc(int * error)1371*a58d3d2aSXin Li OpusDRED *opus_dred_alloc(int *error)
1372*a58d3d2aSXin Li {
1373*a58d3d2aSXin Li #ifdef ENABLE_DRED
1374*a58d3d2aSXin Li   OpusDRED *dec;
1375*a58d3d2aSXin Li   dec = (OpusDRED *)opus_alloc(opus_dred_get_size());
1376*a58d3d2aSXin Li   if (dec == NULL)
1377*a58d3d2aSXin Li   {
1378*a58d3d2aSXin Li     if (error)
1379*a58d3d2aSXin Li       *error = OPUS_ALLOC_FAIL;
1380*a58d3d2aSXin Li     return NULL;
1381*a58d3d2aSXin Li   }
1382*a58d3d2aSXin Li   return dec;
1383*a58d3d2aSXin Li #else
1384*a58d3d2aSXin Li   if (error)
1385*a58d3d2aSXin Li     *error = OPUS_UNIMPLEMENTED;
1386*a58d3d2aSXin Li   return NULL;
1387*a58d3d2aSXin Li #endif
1388*a58d3d2aSXin Li }
1389*a58d3d2aSXin Li 
opus_dred_free(OpusDRED * dec)1390*a58d3d2aSXin Li void opus_dred_free(OpusDRED *dec)
1391*a58d3d2aSXin Li {
1392*a58d3d2aSXin Li #ifdef ENABLE_DRED
1393*a58d3d2aSXin Li   opus_free(dec);
1394*a58d3d2aSXin Li #else
1395*a58d3d2aSXin Li   (void)dec;
1396*a58d3d2aSXin Li #endif
1397*a58d3d2aSXin Li }
1398*a58d3d2aSXin Li 
opus_dred_parse(OpusDREDDecoder * dred_dec,OpusDRED * dred,const unsigned char * data,opus_int32 len,opus_int32 max_dred_samples,opus_int32 sampling_rate,int * dred_end,int defer_processing)1399*a58d3d2aSXin Li int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing)
1400*a58d3d2aSXin Li {
1401*a58d3d2aSXin Li #ifdef ENABLE_DRED
1402*a58d3d2aSXin Li    const unsigned char *payload;
1403*a58d3d2aSXin Li    opus_int32 payload_len;
1404*a58d3d2aSXin Li    int dred_frame_offset=0;
1405*a58d3d2aSXin Li    VALIDATE_DRED_DECODER(dred_dec);
1406*a58d3d2aSXin Li    if (!dred_dec->loaded) return OPUS_UNIMPLEMENTED;
1407*a58d3d2aSXin Li    dred->process_stage = -1;
1408*a58d3d2aSXin Li    payload_len = dred_find_payload(data, len, &payload, &dred_frame_offset);
1409*a58d3d2aSXin Li    if (payload_len < 0)
1410*a58d3d2aSXin Li       return payload_len;
1411*a58d3d2aSXin Li    if (payload != NULL)
1412*a58d3d2aSXin Li    {
1413*a58d3d2aSXin Li       int offset;
1414*a58d3d2aSXin Li       int min_feature_frames;
1415*a58d3d2aSXin Li       offset = 100*max_dred_samples/sampling_rate;
1416*a58d3d2aSXin Li       min_feature_frames = IMIN(2 + offset, 2*DRED_NUM_REDUNDANCY_FRAMES);
1417*a58d3d2aSXin Li       dred_ec_decode(dred, payload, payload_len, min_feature_frames, dred_frame_offset);
1418*a58d3d2aSXin Li       if (!defer_processing)
1419*a58d3d2aSXin Li          opus_dred_process(dred_dec, dred, dred);
1420*a58d3d2aSXin Li       if (dred_end) *dred_end = IMAX(0, -dred->dred_offset*sampling_rate/400);
1421*a58d3d2aSXin Li       return IMAX(0, dred->nb_latents*sampling_rate/25 - dred->dred_offset* sampling_rate/400);
1422*a58d3d2aSXin Li    }
1423*a58d3d2aSXin Li    if (dred_end) *dred_end = 0;
1424*a58d3d2aSXin Li    return 0;
1425*a58d3d2aSXin Li #else
1426*a58d3d2aSXin Li    (void)dred_dec;
1427*a58d3d2aSXin Li    (void)dred;
1428*a58d3d2aSXin Li    (void)data;
1429*a58d3d2aSXin Li    (void)len;
1430*a58d3d2aSXin Li    (void)max_dred_samples;
1431*a58d3d2aSXin Li    (void)sampling_rate;
1432*a58d3d2aSXin Li    (void)defer_processing;
1433*a58d3d2aSXin Li    (void)dred_end;
1434*a58d3d2aSXin Li    return OPUS_UNIMPLEMENTED;
1435*a58d3d2aSXin Li #endif
1436*a58d3d2aSXin Li }
1437*a58d3d2aSXin Li 
opus_dred_process(OpusDREDDecoder * dred_dec,const OpusDRED * src,OpusDRED * dst)1438*a58d3d2aSXin Li int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst)
1439*a58d3d2aSXin Li {
1440*a58d3d2aSXin Li #ifdef ENABLE_DRED
1441*a58d3d2aSXin Li    if (dred_dec == NULL || src == NULL || dst == NULL || (src->process_stage != 1 && src->process_stage != 2))
1442*a58d3d2aSXin Li       return OPUS_BAD_ARG;
1443*a58d3d2aSXin Li    VALIDATE_DRED_DECODER(dred_dec);
1444*a58d3d2aSXin Li    if (!dred_dec->loaded) return OPUS_UNIMPLEMENTED;
1445*a58d3d2aSXin Li    if (src != dst)
1446*a58d3d2aSXin Li       OPUS_COPY(dst, src, 1);
1447*a58d3d2aSXin Li    if (dst->process_stage == 2)
1448*a58d3d2aSXin Li       return OPUS_OK;
1449*a58d3d2aSXin Li    DRED_rdovae_decode_all(&dred_dec->model, dst->fec_features, dst->state, dst->latents, dst->nb_latents, dred_dec->arch);
1450*a58d3d2aSXin Li    dst->process_stage = 2;
1451*a58d3d2aSXin Li    return OPUS_OK;
1452*a58d3d2aSXin Li #else
1453*a58d3d2aSXin Li    (void)dred_dec;
1454*a58d3d2aSXin Li    (void)src;
1455*a58d3d2aSXin Li    (void)dst;
1456*a58d3d2aSXin Li    return OPUS_UNIMPLEMENTED;
1457*a58d3d2aSXin Li #endif
1458*a58d3d2aSXin Li }
1459*a58d3d2aSXin Li 
opus_decoder_dred_decode(OpusDecoder * st,const OpusDRED * dred,opus_int32 dred_offset,opus_int16 * pcm,opus_int32 frame_size)1460*a58d3d2aSXin Li int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size)
1461*a58d3d2aSXin Li {
1462*a58d3d2aSXin Li #ifdef ENABLE_DRED
1463*a58d3d2aSXin Li    VARDECL(float, out);
1464*a58d3d2aSXin Li    int ret, i;
1465*a58d3d2aSXin Li    ALLOC_STACK;
1466*a58d3d2aSXin Li 
1467*a58d3d2aSXin Li    if(frame_size<=0)
1468*a58d3d2aSXin Li    {
1469*a58d3d2aSXin Li       RESTORE_STACK;
1470*a58d3d2aSXin Li       return OPUS_BAD_ARG;
1471*a58d3d2aSXin Li    }
1472*a58d3d2aSXin Li 
1473*a58d3d2aSXin Li    celt_assert(st->channels == 1 || st->channels == 2);
1474*a58d3d2aSXin Li    ALLOC(out, frame_size*st->channels, float);
1475*a58d3d2aSXin Li 
1476*a58d3d2aSXin Li    ret = opus_decode_native(st, NULL, 0, out, frame_size, 0, 0, NULL, 1, dred, dred_offset);
1477*a58d3d2aSXin Li    if (ret > 0)
1478*a58d3d2aSXin Li    {
1479*a58d3d2aSXin Li       for (i=0;i<ret*st->channels;i++)
1480*a58d3d2aSXin Li          pcm[i] = FLOAT2INT16(out[i]);
1481*a58d3d2aSXin Li    }
1482*a58d3d2aSXin Li    RESTORE_STACK;
1483*a58d3d2aSXin Li    return ret;
1484*a58d3d2aSXin Li #else
1485*a58d3d2aSXin Li    (void)st;
1486*a58d3d2aSXin Li    (void)dred;
1487*a58d3d2aSXin Li    (void)dred_offset;
1488*a58d3d2aSXin Li    (void)pcm;
1489*a58d3d2aSXin Li    (void)frame_size;
1490*a58d3d2aSXin Li    return OPUS_UNIMPLEMENTED;
1491*a58d3d2aSXin Li #endif
1492*a58d3d2aSXin Li }
1493*a58d3d2aSXin Li 
opus_decoder_dred_decode_float(OpusDecoder * st,const OpusDRED * dred,opus_int32 dred_offset,float * pcm,opus_int32 frame_size)1494*a58d3d2aSXin Li int opus_decoder_dred_decode_float(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, float *pcm, opus_int32 frame_size)
1495*a58d3d2aSXin Li {
1496*a58d3d2aSXin Li #ifdef ENABLE_DRED
1497*a58d3d2aSXin Li    if(frame_size<=0)
1498*a58d3d2aSXin Li       return OPUS_BAD_ARG;
1499*a58d3d2aSXin Li    return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, 0, dred, dred_offset);
1500*a58d3d2aSXin Li #else
1501*a58d3d2aSXin Li    (void)st;
1502*a58d3d2aSXin Li    (void)dred;
1503*a58d3d2aSXin Li    (void)dred_offset;
1504*a58d3d2aSXin Li    (void)pcm;
1505*a58d3d2aSXin Li    (void)frame_size;
1506*a58d3d2aSXin Li    return OPUS_UNIMPLEMENTED;
1507*a58d3d2aSXin Li #endif
1508*a58d3d2aSXin Li }
1509