12bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
22bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Written by Jean-Marc Valin and Koen Vos */
32bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/*
42bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Redistribution and use in source and binary forms, with or without
52bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   modification, are permitted provided that the following conditions
62bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   are met:
72bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
82bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   - Redistributions of source code must retain the above copyright
92bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   notice, this list of conditions and the following disclaimer.
102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   - Redistributions in binary form must reproduce the above copyright
122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   notice, this list of conditions and the following disclaimer in the
132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   documentation and/or other materials provided with the distribution.
142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian*/
272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef HAVE_CONFIG_H
292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian# include "config.h"
302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef OPUS_BUILD
332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian# 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."
342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__)
372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian# pragma message "You appear to be compiling without optimization, if so opus will be very slow."
382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include <stdarg.h>
412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "celt.h"
422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "opus.h"
432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "entdec.h"
442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "modes.h"
452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "API.h"
462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "stack_alloc.h"
472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "float_cast.h"
482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "opus_private.h"
492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "os_support.h"
502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "structs.h"
512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "define.h"
522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "mathops.h"
532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "cpu_support.h"
542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstruct OpusDecoder {
562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          celt_dec_offset;
572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          silk_dec_offset;
582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          channels;
592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32   Fs;          /** Sampling rate (at the API level) */
602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   silk_DecControlStruct DecControl;
612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          decode_gain;
622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Everything beyond this point gets cleared on a reset */
642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define OPUS_DECODER_RESET_START stream_channels
652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          stream_channels;
662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          bandwidth;
682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          mode;
692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          prev_mode;
702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          frame_size;
712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          prev_redundancy;
722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int          last_packet_duration;
732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef FIXED_POINT
742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16   softclip_mem[2];
752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_uint32  rangeFinal;
782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian};
792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x;
832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decoder_get_size(int channels)
882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int silkDecSizeBytes, celtDecSizeBytes;
902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret;
912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (channels<1 || channels > 2)
922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return 0;
932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = silk_Get_Decoder_Size( &silkDecSizeBytes );
942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(ret)
952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return 0;
962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   silkDecSizeBytes = align(silkDecSizeBytes);
972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celtDecSizeBytes = celt_decoder_get_size(channels);
982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes;
992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
1022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   void *silk_dec;
1042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   CELTDecoder *celt_dec;
1052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret, silkDecSizeBytes;
1062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)
1082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    || (channels!=1&&channels!=2))
1092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
1102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
1122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Initialize SILK encoder */
1132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
1142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret)
1152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_INTERNAL_ERROR;
1162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   silkDecSizeBytes = align(silkDecSizeBytes);
1182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->silk_dec_offset = align(sizeof(OpusDecoder));
1192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes;
1202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   silk_dec = (char*)st+st->silk_dec_offset;
1212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
1222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->stream_channels = st->channels = channels;
1232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->Fs = Fs;
1252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->DecControl.API_sampleRate = st->Fs;
1262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->DecControl.nChannelsAPI      = st->channels;
1272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Reset decoder */
1292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = silk_InitDecoder( silk_dec );
1302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(ret)return OPUS_INTERNAL_ERROR;
1312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Initialize CELT decoder */
1332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = celt_decoder_init(celt_dec, Fs, channels);
1342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR;
1352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));
1372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->prev_mode = 0;
1392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->frame_size = Fs/400;
1402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return OPUS_OK;
1412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh VenkatasubramanianOpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error)
1442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret;
1462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OpusDecoder *st;
1472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)
1482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    || (channels!=1&&channels!=2))
1492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (error)
1512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *error = OPUS_BAD_ARG;
1522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return NULL;
1532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels));
1552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st == NULL)
1562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (error)
1582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *error = OPUS_ALLOC_FAIL;
1592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return NULL;
1602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = opus_decoder_init(st, Fs, channels);
1622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (error)
1632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *error = ret;
1642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret != OPUS_OK)
1652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_free(st);
1672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st = NULL;
1682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return st;
1702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic void smooth_fade(const opus_val16 *in1, const opus_val16 *in2,
1732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_val16 *out, int overlap, int channels,
1742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      const opus_val16 *window, opus_int32 Fs)
1752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i, c;
1772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int inc = 48000/Fs;
1782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (c=0;c<channels;c++)
1792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<overlap;i++)
1812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
1822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val16 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
1832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]),
1842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                                   Q15ONE-w, in1[i*channels+c]), 15);
1852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
1862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic int opus_packet_get_mode(const unsigned char *data)
1902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int mode;
1922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (data[0]&0x80)
1932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      mode = MODE_CELT_ONLY;
1952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if ((data[0]&0x60) == 0x60)
1962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      mode = MODE_HYBRID;
1982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
1992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      mode = MODE_SILK_ONLY;
2002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
2012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return mode;
2022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
2032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
2052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
2062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
2072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   void *silk_dec;
2082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   CELTDecoder *celt_dec;
2092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i, silk_ret=0, celt_ret=0;
2102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ec_dec dec;
2112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 silk_frame_size;
2122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int pcm_silk_size;
2132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_int16, pcm_silk);
2142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int pcm_transition_silk_size;
2152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val16, pcm_transition_silk);
2162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int pcm_transition_celt_size;
2172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val16, pcm_transition_celt);
2182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 *pcm_transition;
2192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int redundant_audio_size;
2202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_val16, redundant_audio);
2212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int audiosize;
2232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int mode;
2242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int transition=0;
2252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int start_band;
2262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int redundancy=0;
2272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int redundancy_bytes = 0;
2282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int celt_to_silk=0;
2292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int c;
2302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int F2_5, F5, F10, F20;
2312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const opus_val16 *window;
2322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_uint32 redundant_rng = 0;
2332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC_STACK;
2342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   silk_dec = (char*)st+st->silk_dec_offset;
2362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
2372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   F20 = st->Fs/50;
2382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   F10 = F20>>1;
2392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   F5 = F10>>1;
2402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   F2_5 = F5>>1;
2412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (frame_size < F2_5)
2422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
2432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
2442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BUFFER_TOO_SMALL;
2452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
2462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Limit frame_size to avoid excessive stack allocations. */
2472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   frame_size = IMIN(frame_size, st->Fs/25*3);
2482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
2492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (len<=1)
2502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
2512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      data = NULL;
2522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* In that case, don't conceal more than what the ToC says */
2532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      frame_size = IMIN(frame_size, st->frame_size);
2542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
2552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (data != NULL)
2562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
2572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      audiosize = st->frame_size;
2582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      mode = st->mode;
2592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ec_dec_init(&dec,(unsigned char*)data,len);
2602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
2612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      audiosize = frame_size;
2622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      mode = st->prev_mode;
2632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (mode == 0)
2652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* If we haven't got any packet yet, all we can do is return zeros */
2672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<audiosize*st->channels;i++)
2682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm[i] = 0;
2692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         RESTORE_STACK;
2702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return audiosize;
2712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
2722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
2742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         10, or 20 (e.g. 12.5 or 30 ms). */
2752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (audiosize > F20)
2762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         do {
2782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0);
2792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            if (ret<0)
2802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
2812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               RESTORE_STACK;
2822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               return ret;
2832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
2842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm += ret*st->channels;
2852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            audiosize -= ret;
2862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         } while (audiosize > 0);
2872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         RESTORE_STACK;
2882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return frame_size;
2892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else if (audiosize < F20)
2902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (audiosize > F10)
2922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            audiosize = F10;
2932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
2942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            audiosize = F5;
2952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
2962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
2972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   pcm_transition_silk_size = ALLOC_NONE;
2992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   pcm_transition_celt_size = ALLOC_NONE;
3002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (data!=NULL && st->prev_mode > 0 && (
3012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
3022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
3032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      )
3042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      transition = 1;
3062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Decide where to allocate the stack memory for pcm_transition */
3072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (mode == MODE_CELT_ONLY)
3082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm_transition_celt_size = F5*st->channels;
3092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
3102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm_transition_silk_size = F5*st->channels;
3112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16);
3132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (transition && mode == MODE_CELT_ONLY)
3142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pcm_transition = pcm_transition_celt;
3162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
3172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (audiosize > frame_size)
3192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/
3212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
3222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
3232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
3242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      frame_size = audiosize;
3252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Don't allocate any memory when in CELT-only mode */
3282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   pcm_silk_size = (mode != MODE_CELT_ONLY) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE;
3292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(pcm_silk, pcm_silk_size, opus_int16);
3302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* SILK processing */
3322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (mode != MODE_CELT_ONLY)
3332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int lost_flag, decoded_samples;
3352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int16 *pcm_ptr = pcm_silk;
3362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (st->prev_mode==MODE_CELT_ONLY)
3382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         silk_InitDecoder( silk_dec );
3392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* The SILK PLC cannot produce frames of less than 10 ms */
3412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);
3422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (data != NULL)
3442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
3452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        st->DecControl.nChannelsInternal = st->stream_channels;
3462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        if( mode == MODE_SILK_ONLY ) {
3472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
3482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              st->DecControl.internalSampleRate = 8000;
3492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
3502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              st->DecControl.internalSampleRate = 12000;
3512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
3522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              st->DecControl.internalSampleRate = 16000;
3532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           } else {
3542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              st->DecControl.internalSampleRate = 16000;
3552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              silk_assert( 0 );
3562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           }
3572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        } else {
3582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           /* Hybrid mode */
3592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           st->DecControl.internalSampleRate = 16000;
3602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        }
3612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian     }
3622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian     lost_flag = data == NULL ? 1 : 2 * decode_fec;
3642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian     decoded_samples = 0;
3652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian     do {
3662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        /* Call SILK decoder */
3672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        int first_frame = decoded_samples == 0;
3682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        silk_ret = silk_Decode( silk_dec, &st->DecControl,
3692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                                lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size );
3702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        if( silk_ret ) {
3712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           if (lost_flag) {
3722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              /* PLC failure should not be fatal */
3732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              silk_frame_size = frame_size;
3742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              for (i=0;i<frame_size*st->channels;i++)
3752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                 pcm_ptr[i] = 0;
3762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           } else {
3772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian             RESTORE_STACK;
3782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian             return OPUS_INTERNAL_ERROR;
3792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian           }
3802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        }
3812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        pcm_ptr += silk_frame_size * st->channels;
3822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian        decoded_samples += silk_frame_size;
3832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } while( decoded_samples < frame_size );
3842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
3852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   start_band = 0;
3872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
3882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian    && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len)
3892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
3902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Check if we have a redundant 0-8 kHz band */
3912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (mode == MODE_HYBRID)
3922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         redundancy = ec_dec_bit_logp(&dec, 12);
3932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
3942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         redundancy = 1;
3952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (redundancy)
3962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
3972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         celt_to_silk = ec_dec_bit_logp(&dec, 1);
3982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* redundancy_bytes will be at least two, in the non-hybrid
3992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            case due to the ec_tell() check above */
4002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         redundancy_bytes = mode==MODE_HYBRID ?
4012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               (opus_int32)ec_dec_uint(&dec, 256)+2 :
4022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               len-((ec_tell(&dec)+7)>>3);
4032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         len -= redundancy_bytes;
4042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* This is a sanity check. It should never happen for a valid
4052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            packet, so the exact behaviour is not normative. */
4062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (len*8 < ec_tell(&dec))
4072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
4082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            len = 0;
4092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            redundancy_bytes = 0;
4102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            redundancy = 0;
4112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
4122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Shrink decoder because of raw bits */
4132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         dec.storage -= redundancy_bytes;
4142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
4152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (mode != MODE_CELT_ONLY)
4172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      start_band = 17;
4182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int endband=21;
4212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      switch(st->bandwidth)
4232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
4242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_BANDWIDTH_NARROWBAND:
4252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         endband = 13;
4262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         break;
4272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_BANDWIDTH_MEDIUMBAND:
4282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_BANDWIDTH_WIDEBAND:
4292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         endband = 17;
4302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         break;
4312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_BANDWIDTH_SUPERWIDEBAND:
4322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         endband = 19;
4332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         break;
4342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_BANDWIDTH_FULLBAND:
4352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         endband = 21;
4362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         break;
4372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
4382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband));
4392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels));
4402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (redundancy)
4432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      transition = 0;
4452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pcm_transition_silk_size=ALLOC_NONE;
4462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);
4492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (transition && mode != MODE_CELT_ONLY)
4512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      pcm_transition = pcm_transition_silk;
4532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
4542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Only allocation memory for redundancy if/when needed */
4572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
4582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(redundant_audio, redundant_audio_size, opus_val16);
4592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* 5 ms redundant frame for CELT->SILK*/
4612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (redundancy && celt_to_silk)
4622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
4642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
4652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                          redundant_audio, F5, NULL);
4662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
4672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* MUST be after PLC */
4702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band));
4712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (mode != MODE_SILK_ONLY)
4732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int celt_frame_size = IMIN(F20, frame_size);
4752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Make sure to discard any previous CELT state */
4762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
4772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
4782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Decode CELT */
4792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data,
4802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                                     len, pcm, celt_frame_size, &dec);
4812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
4822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      unsigned char silence[2] = {0xFF, 0xFF};
4832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<frame_size*st->channels;i++)
4842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[i] = 0;
4852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* For hybrid -> SILK transitions, we let the CELT MDCT
4862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         do a fade-out by decoding a silence frame */
4872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
4882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
4892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
4902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL);
4912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
4922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (mode != MODE_CELT_ONLY)
4952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
4972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<frame_size*st->channels;i++)
4982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[i] = SAT16(pcm[i] + pcm_silk[i]);
4992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
5002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<frame_size*st->channels;i++)
5012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]);
5022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
5032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      const CELTMode *celt_mode;
5072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode));
5082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      window = celt_mode->window;
5092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* 5 ms redundant frame for SILK->CELT */
5122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (redundancy && !celt_to_silk)
5132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
5152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
5162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL);
5182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
5192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
5202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
5212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (redundancy && celt_to_silk)
5232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (c=0;c<st->channels;c++)
5252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
5262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<F2_5;i++)
5272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm[st->channels*i+c] = redundant_audio[st->channels*i+c];
5282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
5292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5,
5302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs);
5312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (transition)
5332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (audiosize >= F5)
5352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
5362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<st->channels*F2_5;i++)
5372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            pcm[i] = pcm_transition[i];
5382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
5392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                     pcm+st->channels*F2_5, F2_5,
5402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                     st->channels, window, st->Fs);
5412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else {
5422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Not enough time to do a clean transition, but we do it anyway
5432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            This will not preserve amplitude perfectly and may introduce
5442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            a bit of temporal aliasing, but it shouldn't be too bad and
5452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            that's pretty much the best we can do. In any case, generating this
5462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            transition it pretty silly in the first place */
5472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         smooth_fade(pcm_transition, pcm,
5482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                     pcm, F2_5,
5492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                     st->channels, window, st->Fs);
5502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
5512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(st->decode_gain)
5542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_val32 gain;
5562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain));
5572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<frame_size*st->channels;i++)
5582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
5592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val32 x;
5602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         x = MULT16_32_P16(pcm[i],gain);
5612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[i] = SATURATE(x, 32767);
5622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
5632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (len <= 1)
5662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->rangeFinal = 0;
5672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
5682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->rangeFinal = dec.rng ^ redundant_rng;
5692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->prev_mode = mode;
5712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->prev_redundancy = redundancy && !celt_to_silk;
5722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (celt_ret>=0)
5742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels))
5762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OPUS_PRINT_INT(audiosize);
5772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
5782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
5802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return celt_ret < 0 ? celt_ret : audiosize;
5812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
5832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decode_native(OpusDecoder *st, const unsigned char *data,
5852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec,
5862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int self_delimited, opus_int32 *packet_offset, int soft_clip)
5872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
5882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i, nb_samples;
5892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int count, offset;
5902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   unsigned char toc;
5912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
5922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* 48 x 2.5 ms = 120 ms */
5932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int16 size[48];
5942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (decode_fec<0 || decode_fec>1)
5952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
5962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
5972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0)
5982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
5992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (len==0 || data==NULL)
6002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
6012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int pcm_count=0;
6022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      do {
6032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int ret;
6042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0);
6052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (ret<0)
6062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            return ret;
6072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm_count += ret;
6082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } while (pcm_count < frame_size);
6092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_assert(pcm_count == frame_size);
6102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels))
6112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OPUS_PRINT_INT(pcm_count);
6122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->last_packet_duration = pcm_count;
6132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return pcm_count;
6142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if (len<0)
6152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
6162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   packet_mode = opus_packet_get_mode(data);
6182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   packet_bandwidth = opus_packet_get_bandwidth(data);
6192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
6202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   packet_stream_channels = opus_packet_get_nb_channels(data);
6212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
6232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                                  size, &offset, packet_offset);
6242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (count<0)
6252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return count;
6262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   data += offset;
6282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (decode_fec)
6302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
6312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int duration_copy;
6322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int ret;
6332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* If no FEC can be present, run the PLC (recursive call) */
6342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)
6352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip);
6362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Otherwise, run the PLC on everything except the size for which we might have FEC */
6372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      duration_copy = st->last_packet_duration;
6382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (frame_size-packet_frame_size!=0)
6392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
6402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip);
6412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (ret<0)
6422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
6432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            st->last_packet_duration = duration_copy;
6442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            return ret;
6452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
6462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         celt_assert(ret==frame_size-packet_frame_size);
6472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
6482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Complete with FEC */
6492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->mode = packet_mode;
6502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->bandwidth = packet_bandwidth;
6512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->frame_size = packet_frame_size;
6522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->stream_channels = packet_stream_channels;
6532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size),
6542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            packet_frame_size, 1);
6552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (ret<0)
6562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return ret;
6572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else {
6582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels))
6592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            OPUS_PRINT_INT(frame_size);
6602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         st->last_packet_duration = frame_size;
6612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return frame_size;
6622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
6632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
6642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (count*packet_frame_size > frame_size)
6662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BUFFER_TOO_SMALL;
6672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Update the state as the last step to avoid updating it on an invalid packet */
6692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->mode = packet_mode;
6702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->bandwidth = packet_bandwidth;
6712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->frame_size = packet_frame_size;
6722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->stream_channels = packet_stream_channels;
6732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   nb_samples=0;
6752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=0;i<count;i++)
6762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
6772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int ret;
6782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0);
6792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (ret<0)
6802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return ret;
6812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_assert(ret==packet_frame_size);
6822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      data += size[i];
6832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      nb_samples += ret;
6842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
6852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->last_packet_duration = nb_samples;
6862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels))
6872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OPUS_PRINT_INT(nb_samples);
6882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef FIXED_POINT
6892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (soft_clip)
6902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem);
6912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
6922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->softclip_mem[0]=st->softclip_mem[1]=0;
6932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
6942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return nb_samples;
6952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
6962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
6982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decode(OpusDecoder *st, const unsigned char *data,
7002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
7012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
7022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(frame_size<=0)
7032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
7042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0);
7052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
7062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef DISABLE_FLOAT_API
7082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decode_float(OpusDecoder *st, const unsigned char *data,
7092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 len, float *pcm, int frame_size, int decode_fec)
7102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
7112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_int16, out);
7122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret, i;
7132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC_STACK;
7142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(frame_size<=0)
7162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
7182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
7192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(out, frame_size*st->channels, opus_int16);
7212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0);
7232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret > 0)
7242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<ret*st->channels;i++)
7262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[i] = (1.f/32768.f)*(out[i]);
7272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
7292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return ret;
7302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
7312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
7322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
7352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decode(OpusDecoder *st, const unsigned char *data,
7362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
7372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
7382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(float, out);
7392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret, i;
7402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC_STACK;
7412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(frame_size<=0)
7432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
7452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
7462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(out, frame_size*st->channels, float);
7492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1);
7512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret > 0)
7522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<ret*st->channels;i++)
7542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[i] = FLOAT2INT16(out[i]);
7552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
7572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return ret;
7582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
7592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decode_float(OpusDecoder *st, const unsigned char *data,
7612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
7622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
7632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(frame_size<=0)
7642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
7652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0);
7662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
7672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
7692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decoder_ctl(OpusDecoder *st, int request, ...)
7712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
7722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret = OPUS_OK;
7732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_list ap;
7742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   void *silk_dec;
7752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   CELTDecoder *celt_dec;
7762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   silk_dec = (char*)st+st->silk_dec_offset;
7782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
7792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_start(ap, request);
7822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   switch (request)
7842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_BANDWIDTH_REQUEST:
7862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 *value = va_arg(ap, opus_int32*);
7882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
7892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
7902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
7912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
7922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value = st->bandwidth;
7932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
7952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_FINAL_RANGE_REQUEST:
7962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
7972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_uint32 *value = va_arg(ap, opus_uint32*);
7982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
7992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
8012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
8022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value = st->rangeFinal;
8032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
8052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_RESET_STATE:
8062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
8082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            sizeof(OpusDecoder)-
8092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ((char*)&st->OPUS_DECODER_RESET_START - (char*)st));
8102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
8122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      silk_InitDecoder( silk_dec );
8132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->stream_channels = st->channels;
8142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->frame_size = st->Fs/400;
8152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
8172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_SAMPLE_RATE_REQUEST:
8182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 *value = va_arg(ap, opus_int32*);
8202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
8212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
8232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
8242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value = st->Fs;
8252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
8272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_PITCH_REQUEST:
8282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 *value = va_arg(ap, opus_int32*);
8302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
8312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
8332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
8342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (st->prev_mode == MODE_CELT_ONLY)
8352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
8362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
8372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value = st->DecControl.prevPitchLag;
8382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
8402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_GAIN_REQUEST:
8412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 *value = va_arg(ap, opus_int32*);
8432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
8442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
8462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
8472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value = st->decode_gain;
8482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
8502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_SET_GAIN_REQUEST:
8512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       opus_int32 value = va_arg(ap, opus_int32);
8532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       if (value<-32768 || value>32767)
8542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       {
8552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian          goto bad_arg;
8562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       }
8572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian       st->decode_gain = value;
8582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
8602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
8612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_uint32 *value = va_arg(ap, opus_uint32*);
8632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (!value)
8642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_arg;
8662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
8672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *value = st->last_packet_duration;
8682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   break;
8702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   default:
8712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
8722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ret = OPUS_UNIMPLEMENTED;
8732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
8742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_end(ap);
8772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return ret;
8782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianbad_arg:
8792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_end(ap);
8802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return OPUS_BAD_ARG;
8812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
8822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianvoid opus_decoder_destroy(OpusDecoder *st)
8842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
8852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_free(st);
8862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
8872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_packet_get_bandwidth(const unsigned char *data)
8902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
8912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int bandwidth;
8922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (data[0]&0x80)
8932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      bandwidth = OPUS_BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3);
8952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
8962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         bandwidth = OPUS_BANDWIDTH_NARROWBAND;
8972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if ((data[0]&0x60) == 0x60)
8982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      bandwidth = (data[0]&0x10) ? OPUS_BANDWIDTH_FULLBAND :
9002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                                   OPUS_BANDWIDTH_SUPERWIDEBAND;
9012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
9022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      bandwidth = OPUS_BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3);
9032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return bandwidth;
9052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_packet_get_samples_per_frame(const unsigned char *data,
9082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 Fs)
9092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int audiosize;
9112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (data[0]&0x80)
9122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      audiosize = ((data[0]>>3)&0x3);
9142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      audiosize = (Fs<<audiosize)/400;
9152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else if ((data[0]&0x60) == 0x60)
9162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
9182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
9192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      audiosize = ((data[0]>>3)&0x3);
9202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (audiosize == 3)
9212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         audiosize = Fs*60/1000;
9222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
9232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         audiosize = (Fs<<audiosize)/100;
9242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return audiosize;
9262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_packet_get_nb_channels(const unsigned char *data)
9292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return (data[0]&0x4) ? 2 : 1;
9312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len)
9342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int count;
9362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (len<1)
9372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
9382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   count = packet[0]&0x3;
9392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (count==0)
9402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return 1;
9412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else if (count!=3)
9422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return 2;
9432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else if (len<2)
9442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_INVALID_PACKET;
9452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
9462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return packet[1]&0x3F;
9472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len,
9502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_int32 Fs)
9512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int samples;
9532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int count = opus_packet_get_nb_frames(packet, len);
9542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (count<0)
9562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return count;
9572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   samples = count*opus_packet_get_samples_per_frame(packet, Fs);
9592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Can't have more than 120 ms */
9602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (samples*25 > Fs*3)
9612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_INVALID_PACKET;
9622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
9632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return samples;
9642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
9652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_decoder_get_nb_samples(const OpusDecoder *dec,
9672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      const unsigned char packet[], opus_int32 len)
9682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
9692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_packet_get_nb_samples(packet, len, dec->Fs);
9702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
971