12bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* Copyright (c) 2007-2008 CSIRO
22bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Copyright (c) 2007-2010 Xiph.Org Foundation
32bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Copyright (c) 2008 Gregory Maxwell
42bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Written by Jean-Marc Valin and Gregory Maxwell */
52bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/*
62bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Redistribution and use in source and binary forms, with or without
72bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   modification, are permitted provided that the following conditions
82bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   are met:
92bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   - Redistributions of source code must retain the above copyright
112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   notice, this list of conditions and the following disclaimer.
122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   - Redistributions in binary form must reproduce the above copyright
142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   notice, this list of conditions and the following disclaimer in the
152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   documentation and/or other materials provided with the distribution.
162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian*/
292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef HAVE_CONFIG_H
312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "config.h"
322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define CELT_DECODER_C
352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "cpu_support.h"
372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "os_support.h"
382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "mdct.h"
392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include <math.h>
402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "celt.h"
412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "pitch.h"
422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "bands.h"
432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "modes.h"
442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "entcode.h"
452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "quant_bands.h"
462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "rate.h"
472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "stack_alloc.h"
482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "mathops.h"
492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "float_cast.h"
502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include <stdarg.h>
512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "celt_lpc.h"
522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#include "vq.h"
532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
54c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT)
55c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#define NORM_ALIASING_HACK
56c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/**********************************************************************/
582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/*                                                                    */
592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/*                             DECODER                                */
602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/*                                                                    */
612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/**********************************************************************/
622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define DECODE_BUFFER_SIZE 2048
632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/** Decoder state
652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian @brief Decoder state
662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian */
672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstruct OpusCustomDecoder {
682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const OpusCustomMode *mode;
692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int overlap;
702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int channels;
712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int stream_channels;
722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int downsample;
742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int start, end;
752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int signalling;
760c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   int disable_inv;
772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int arch;
782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Everything beyond this point gets cleared on a reset */
802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define DECODER_RESET_START rng
812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_uint32 rng;
832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int error;
842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int last_pitch_index;
852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int loss_count;
86d03c373974c945b4b62b59b873522387418a2a3fFelicia Lim   int skip_plc;
872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int postfilter_period;
882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int postfilter_period_old;
892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 postfilter_gain;
902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 postfilter_gain_old;
912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int postfilter_tapset;
922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int postfilter_tapset_old;
932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_sig preemph_memD[2];
952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* opus_val16 lpc[],  Size = channels*LPC_ORDER */
982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */
992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */
1002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */
1012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
1022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian};
1032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint celt_decoder_get_size(int channels)
1052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
1072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return opus_custom_decoder_get_size(mode, channels);
1082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh VenkatasubramanianOPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
1112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int size = sizeof(struct CELTDecoder)
1132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
1142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            + channels*LPC_ORDER*sizeof(opus_val16)
1152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            + 4*2*mode->nbEBands*sizeof(opus_val16);
1162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return size;
1172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef CUSTOM_MODES
1202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh VenkatasubramanianCELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
1212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret;
1232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
1242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = opus_custom_decoder_init(st, mode, channels);
1252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret != OPUS_OK)
1262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_custom_decoder_destroy(st);
1282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st = NULL;
1292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
1302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (error)
1312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      *error = ret;
1322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return st;
1332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif /* CUSTOM_MODES */
1352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels)
1372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int ret;
1392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
1402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret != OPUS_OK)
1412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return ret;
1422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->downsample = resampling_factor(sampling_rate);
1432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st->downsample==0)
1442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
1452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
1462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_OK;
1472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh VenkatasubramanianOPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
1502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (channels < 0 || channels > 2)
1522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
1532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st==NULL)
1552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_ALLOC_FAIL;
1562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
1582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->mode = mode;
1602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->overlap = mode->overlap;
1612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->stream_channels = st->channels = channels;
1622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->downsample = 1;
1642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->start = 0;
1652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->end = st->mode->effEBands;
1662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->signalling = 1;
1670c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#ifdef ENABLE_UPDATE_DRAFT
1680c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   st->disable_inv = channels == 1;
1690c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#else
1700c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   st->disable_inv = 0;
1710c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#endif
1722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->arch = opus_select_arch();
1732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
1752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return OPUS_OK;
1772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef CUSTOM_MODES
1802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianvoid opus_custom_decoder_destroy(CELTDecoder *st)
1812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_free(st);
1832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif /* CUSTOM_MODES */
1852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1860c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#ifndef CUSTOM_MODES
1870c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim/* Special case for stereo with no downsampling and no accumulation. This is
1880c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   quite common and we can make it faster by processing both channels in the
1890c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   same loop, reducing overhead due to the dependency loop in the IIR filter. */
1900c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Limstatic void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0,
1910c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      celt_sig *mem)
1920c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim{
1930c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   celt_sig * OPUS_RESTRICT x0;
1940c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   celt_sig * OPUS_RESTRICT x1;
1950c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   celt_sig m0, m1;
1960c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   int j;
1970c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   x0=in[0];
1980c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   x1=in[1];
1990c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   m0 = mem[0];
2000c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   m1 = mem[1];
2010c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   for (j=0;j<N;j++)
2020c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   {
2030c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      celt_sig tmp0, tmp1;
2040c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      /* Add VERY_SMALL to x[] first to reduce dependency chain. */
2050c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      tmp0 = x0[j] + VERY_SMALL + m0;
2060c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      tmp1 = x1[j] + VERY_SMALL + m1;
2070c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      m0 = MULT16_32_Q15(coef0, tmp0);
2080c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      m1 = MULT16_32_Q15(coef0, tmp1);
2090c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      pcm[2*j  ] = SCALEOUT(SIG2WORD16(tmp0));
2100c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1));
2110c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   }
2120c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   mem[0] = m0;
2130c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   mem[1] = m1;
2140c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim}
2150c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#endif
2162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
2172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef RESYNTH
2182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic
2192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
220c91ee5b5642fcc4969150f73d5f6848f88bf1638flimvoid deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef,
221c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      celt_sig *mem, int accum)
2222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
2232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int c;
2242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int Nd;
2252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int apply_downsampling=0;
2262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 coef0;
227c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   VARDECL(celt_sig, scratch);
228c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   SAVE_STACK;
2290c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#ifndef CUSTOM_MODES
2300c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   /* Short version for common case. */
2310c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   if (downsample == 1 && C == 2 && !accum)
2320c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   {
2330c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
2340c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      return;
2350c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   }
2360c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#endif
237c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#ifndef FIXED_POINT
238c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   (void)accum;
239c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   celt_assert(accum==0);
240c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
241c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   ALLOC(scratch, N, celt_sig);
2422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   coef0 = coef[0];
2432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   Nd = N/downsample;
2442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   c=0; do {
2452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int j;
2462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_sig * OPUS_RESTRICT x;
2472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_val16  * OPUS_RESTRICT y;
2482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      celt_sig m = mem[c];
2492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      x =in[c];
2502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      y = pcm+c;
2512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef CUSTOM_MODES
2522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (coef[1] != 0)
2532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val16 coef1 = coef[1];
2552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val16 coef3 = coef[3];
2562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (j=0;j<N;j++)
2572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
2582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            celt_sig tmp = x[j] + m + VERY_SMALL;
2592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            m = MULT16_32_Q15(coef0, tmp)
2602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                          - MULT16_32_Q15(coef1, x[j]);
2612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            tmp = SHL32(MULT16_32_Q15(coef3, tmp), 2);
2622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            scratch[j] = tmp;
2632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
2642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         apply_downsampling=1;
2652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else
2662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
2672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (downsample>1)
2682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
2692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Shortcut for the standard (non-custom modes) case */
2702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (j=0;j<N;j++)
2712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
2720c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            celt_sig tmp = x[j] + VERY_SMALL + m;
2732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            m = MULT16_32_Q15(coef0, tmp);
2742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            scratch[j] = tmp;
2752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
2762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         apply_downsampling=1;
2772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else {
2782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Shortcut for the standard (non-custom modes) case */
279c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#ifdef FIXED_POINT
280c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         if (accum)
2812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
282c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            for (j=0;j<N;j++)
283c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            {
284c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               celt_sig tmp = x[j] + m + VERY_SMALL;
285c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               m = MULT16_32_Q15(coef0, tmp);
286c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp))));
287c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            }
288c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         } else
289c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
290c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         {
291c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            for (j=0;j<N;j++)
292c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            {
2930c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim               celt_sig tmp = x[j] + VERY_SMALL + m;
294c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               m = MULT16_32_Q15(coef0, tmp);
295c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               y[j*C] = SCALEOUT(SIG2WORD16(tmp));
296c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            }
2972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
2982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
2992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      mem[c] = m;
3002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (apply_downsampling)
3022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
3032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Perform down-sampling */
304c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#ifdef FIXED_POINT
305c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         if (accum)
306c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         {
307c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            for (j=0;j<Nd;j++)
308c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(scratch[j*downsample]))));
309c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         } else
310c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
311c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         {
312c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            for (j=0;j<Nd;j++)
313c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               y[j*C] = SCALEOUT(SIG2WORD16(scratch[j*downsample]));
314c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         }
3152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
3162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } while (++c<C);
317c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   RESTORE_STACK;
3182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
3192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
3202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef RESYNTH
3212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic
3222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
323c91ee5b5642fcc4969150f73d5f6848f88bf1638flimvoid celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
324c91ee5b5642fcc4969150f73d5f6848f88bf1638flim                    opus_val16 *oldBandE, int start, int effEnd, int C, int CC,
325c91ee5b5642fcc4969150f73d5f6848f88bf1638flim                    int isTransient, int LM, int downsample,
326c91ee5b5642fcc4969150f73d5f6848f88bf1638flim                    int silence, int arch)
3272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
328c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int c, i;
329c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int M;
330c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int b;
3312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int B;
332c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int N, NB;
3332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int shift;
334c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int nbEBands;
335c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int overlap;
336c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   VARDECL(celt_sig, freq);
337c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   SAVE_STACK;
338c91ee5b5642fcc4969150f73d5f6848f88bf1638flim
339c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   overlap = mode->overlap;
340c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   nbEBands = mode->nbEBands;
341c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   N = mode->shortMdctSize<<LM;
342c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   ALLOC(freq, N, celt_sig); /**< Interleaved signal MDCTs */
343c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   M = 1<<LM;
3442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
345c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   if (isTransient)
3462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
347c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      B = M;
348c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      NB = mode->shortMdctSize;
3492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      shift = mode->maxLM;
3502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
3512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      B = 1;
352c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      NB = mode->shortMdctSize<<LM;
3532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      shift = mode->maxLM-LM;
3542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
355c91ee5b5642fcc4969150f73d5f6848f88bf1638flim
356c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   if (CC==2&&C==1)
357c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   {
358c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* Copying a mono streams to two channels */
359c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      celt_sig *freq2;
360c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
361c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            downsample, silence);
362c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* Store a temporary copy in the output buffer because the IMDCT destroys its input. */
363c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      freq2 = out_syn[1]+overlap/2;
364c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      OPUS_COPY(freq2, freq, N);
3652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (b=0;b<B;b++)
366c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
367c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      for (b=0;b<B;b++)
368c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B, arch);
369c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   } else if (CC==1&&C==2)
370c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   {
371c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* Downmixing a stereo stream to mono */
372c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      celt_sig *freq2;
373c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      freq2 = out_syn[0]+overlap/2;
374c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
375c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            downsample, silence);
376c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* Use the output buffer as temp array before downmixing. */
377c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
378c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            downsample, silence);
379c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      for (i=0;i<N;i++)
3800c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim         freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
381c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      for (b=0;b<B;b++)
382c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
383c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   } else {
384c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* Normal case (mono or stereo) */
385c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      c=0; do {
386c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
387c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               downsample, silence);
388c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         for (b=0;b<B;b++)
389c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
390c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      } while (++c<CC);
391c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   }
3920c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
3930c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      or in the */
3940c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   c=0; do {
3950c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      for (i=0;i<N;i++)
3960c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim         out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
3970c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim   } while (++c<CC);
398c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   RESTORE_STACK;
3992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
4002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianstatic void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
4022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
4032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i, curr, tf_select;
4042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int tf_select_rsv;
4052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int tf_changed;
4062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int logp;
4072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_uint32 budget;
4082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_uint32 tell;
4092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   budget = dec->storage*8;
4112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tell = ec_tell(dec);
4122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   logp = isTransient ? 2 : 4;
4132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tf_select_rsv = LM>0 && tell+logp+1<=budget;
4142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   budget -= tf_select_rsv;
4152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tf_changed = curr = 0;
4162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=start;i<end;i++)
4172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (tell+logp<=budget)
4192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
4202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         curr ^= ec_dec_bit_logp(dec, logp);
4212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         tell = ec_tell(dec);
4222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         tf_changed |= curr;
4232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
4242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      tf_res[i] = curr;
4252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      logp = isTransient ? 4 : 5;
4262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tf_select = 0;
4282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (tf_select_rsv &&
4292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian     tf_select_table[LM][4*isTransient+0+tf_changed] !=
4302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian     tf_select_table[LM][4*isTransient+2+tf_changed])
4312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      tf_select = ec_dec_bit_logp(dec, 1);
4332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   for (i=start;i<end;i++)
4352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
4362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
4372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
4382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
4392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
4412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
4422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   current value corresponds to a pitch of 66.67 Hz. */
4432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define PLC_PITCH_LAG_MAX (720)
4442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
4452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   pitch of 480 Hz. */
4462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#define PLC_PITCH_LAG_MIN (100)
4472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
448c91ee5b5642fcc4969150f73d5f6848f88bf1638flimstatic int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
449c91ee5b5642fcc4969150f73d5f6848f88bf1638flim{
450c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int pitch_index;
451c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   VARDECL( opus_val16, lp_pitch_buf );
452c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   SAVE_STACK;
453c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
454c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   pitch_downsample(decode_mem, lp_pitch_buf,
455c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         DECODE_BUFFER_SIZE, C, arch);
456c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
457c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
458c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
459c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
460c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   RESTORE_STACK;
461c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   return pitch_index;
462c91ee5b5642fcc4969150f73d5f6848f88bf1638flim}
463c91ee5b5642fcc4969150f73d5f6848f88bf1638flim
464c91ee5b5642fcc4969150f73d5f6848f88bf1638flimstatic void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
4652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
4662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int c;
4672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int i;
4682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const int C = st->channels;
4692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_sig *decode_mem[2];
4702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_sig *out_syn[2];
4712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 *lpc;
4722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
4732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const OpusCustomMode *mode;
4742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int nbEBands;
4752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int overlap;
4762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int start;
4772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int loss_count;
4782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int noise_based;
4792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const opus_int16 *eBands;
4802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   SAVE_STACK;
4812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mode = st->mode;
4832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   nbEBands = mode->nbEBands;
4842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   overlap = mode->overlap;
4852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   eBands = mode->eBands;
4862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   c=0; do {
4882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
4892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
4902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } while (++c<C);
4912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*C);
4922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   oldBandE = lpc+C*LPC_ORDER;
4932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   oldLogE = oldBandE + 2*nbEBands;
4942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   oldLogE2 = oldLogE + 2*nbEBands;
4952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   backgroundLogE = oldLogE2  + 2*nbEBands;
4962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
4972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   loss_count = st->loss_count;
4982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   start = st->start;
499d03c373974c945b4b62b59b873522387418a2a3fFelicia Lim   noise_based = loss_count >= 5 || start != 0 || st->skip_plc;
5002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (noise_based)
5012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
5022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Noise-based PLC/CNG */
503c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#ifdef NORM_ALIASING_HACK
504c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      celt_norm *X;
505c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#else
5062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      VARDECL(celt_norm, X);
507c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
5082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_uint32 seed;
5092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int end;
5102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int effEnd;
511c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      opus_val16 decay;
5122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      end = st->end;
5132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      effEnd = IMAX(start, IMIN(end, mode->effEBands));
5142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
515c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#ifdef NORM_ALIASING_HACK
516c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* This is an ugly hack that breaks aliasing rules and would be easily broken,
517c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         but it saves almost 4kB of stack. */
518c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      X = (celt_norm*)(out_syn[C-1]+overlap/2);
519c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#else
5202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ALLOC(X, C*N, celt_norm);   /**< Interleaved normalised MDCTs */
521c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
5222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
523c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* Energy decay */
524c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      decay = loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT);
525c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      c=0; do
526c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      {
527c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         for (i=start;i<end;i++)
528c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            oldBandE[c*nbEBands+i] = MAX16(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
529c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      } while (++c<C);
5302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      seed = st->rng;
5312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (c=0;c<C;c++)
5322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
5332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=start;i<effEnd;i++)
5342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
5352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            int j;
5362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            int boffs;
5372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            int blen;
5382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            boffs = N*c+(eBands[i]<<LM);
5392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            blen = (eBands[i+1]-eBands[i])<<LM;
5402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (j=0;j<blen;j++)
5412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
5422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               seed = celt_lcg_rand(seed);
5432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
5442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
545c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            renormalise_vector(X+boffs, blen, Q15ONE, st->arch);
5462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
5472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
5482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->rng = seed;
5492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      c=0; do {
5512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OPUS_MOVE(decode_mem[c], decode_mem[c]+N,
5522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               DECODE_BUFFER_SIZE-N+(overlap>>1));
5532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } while (++c<C);
554c91ee5b5642fcc4969150f73d5f6848f88bf1638flim
555c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
5562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
5572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Pitch-based PLC */
5582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      const opus_val16 *window;
5590c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      opus_val16 *exc;
5602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      opus_val16 fade = Q15ONE;
5612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int pitch_index;
5622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      VARDECL(opus_val32, etmp);
5630c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      VARDECL(opus_val16, _exc);
5642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (loss_count == 0)
5662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
567c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch);
5682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } else {
5692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pitch_index = st->last_pitch_index;
5702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         fade = QCONST16(.8f,15);
5712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
5722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ALLOC(etmp, overlap, opus_val32);
5740c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      ALLOC(_exc, MAX_PERIOD+LPC_ORDER, opus_val16);
5750c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      exc = _exc+LPC_ORDER;
5762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      window = mode->window;
5772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      c=0; do {
5782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val16 decay;
5792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val16 attenuation;
5802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val32 S1=0;
5812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         celt_sig *buf;
5822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int extrapolation_offset;
5832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int extrapolation_len;
5842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int exc_length;
5852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int j;
5862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         buf = decode_mem[c];
5882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<MAX_PERIOD;i++) {
5892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT);
5902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
5912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
5922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (loss_count == 0)
5932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
5942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_val32 ac[LPC_ORDER+1];
5952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* Compute LPC coefficients for the last MAX_PERIOD samples before
5962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               the first loss so we can work in the excitation-filter domain. */
5972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            _celt_autocorr(exc, ac, window, overlap,
5982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                   LPC_ORDER, MAX_PERIOD, st->arch);
5992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* Add a noise floor of -40 dB. */
6002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
6012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ac[0] += SHR32(ac[0],13);
6022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
6032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            ac[0] *= 1.0001f;
6042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
6052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* Use lag windowing to stabilize the Levinson-Durbin recursion. */
6062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (i=1;i<=LPC_ORDER;i++)
6072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
6082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
6092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
6102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
6112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
6122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               ac[i] -= ac[i]*(0.008f*0.008f)*i*i;
6132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
6142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
6152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
6160c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#ifdef FIXED_POINT
6170c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim         /* For fixed-point, apply bandwidth expansion until we can guarantee that
6180c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            no overflow can happen in the IIR filter. This means:
6190c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            32768*sum(abs(filter)) < 2^31 */
6200c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim         while (1) {
6210c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            opus_val16 tmp=Q15ONE;
6220c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            opus_val32 sum=QCONST16(1., SIG_SHIFT);
6230c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            for (i=0;i<LPC_ORDER;i++)
6240c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim               sum += ABS16(lpc[c*LPC_ORDER+i]);
6250c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            if (sum < 65535) break;
6260c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            for (i=0;i<LPC_ORDER;i++)
6270c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            {
6280c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim               tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
6290c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim               lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
6300c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            }
6310c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim         }
6320c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#endif
6332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
6342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* We want the excitation for 2 pitch periods in order to look for a
6352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            decaying signal, but we can't get more than MAX_PERIOD. */
6362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         exc_length = IMIN(2*pitch_index, MAX_PERIOD);
6372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Initialize the LPC history with the samples just before the start
6382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            of the region for which we're computing the excitation. */
6392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
6402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (i=0;i<LPC_ORDER;i++)
6412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
6420c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim               exc[MAX_PERIOD-exc_length-LPC_ORDER+i] =
6430c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim                     ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-LPC_ORDER+i], SIG_SHIFT);
6442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
6452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* Compute the excitation for exc_length samples before the loss. */
6462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
6470c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim                  exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, st->arch);
6482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
6492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Check if the waveform is decaying, and if so how fast.
6512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            We do this to avoid adding energy when concealing in a segment
6522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            with decaying energy. */
6532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
6542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_val32 E1=1, E2=1;
6552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            int decay_length;
6562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
6572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            int shift = IMAX(0,2*celt_zlog2(celt_maxabs16(&exc[MAX_PERIOD-exc_length], exc_length))-20);
6582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
6592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            decay_length = exc_length>>1;
6602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (i=0;i<decay_length;i++)
6612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
6622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               opus_val16 e;
6632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               e = exc[MAX_PERIOD-decay_length+i];
6642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               E1 += SHR32(MULT16_16(e, e), shift);
6652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               e = exc[MAX_PERIOD-2*decay_length+i];
6662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               E2 += SHR32(MULT16_16(e, e), shift);
6672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
6682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            E1 = MIN32(E1, E2);
6692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            decay = celt_sqrt(frac_div32(SHR32(E1, 1), E2));
6702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
6712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Move the decoder memory one frame to the left to give us room to
6732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            add the data for the new frame. We ignore the overlap that extends
6742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            past the end of the buffer, because we aren't going to use it. */
6752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OPUS_MOVE(buf, buf+N, DECODE_BUFFER_SIZE-N);
6762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
6772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Extrapolate from the end of the excitation with a period of
6782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            "pitch_index", scaling down each period by an additional factor of
6792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            "decay". */
6802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         extrapolation_offset = MAX_PERIOD-pitch_index;
6812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* We need to extrapolate enough samples to cover a complete MDCT
6822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            window (including overlap/2 samples on both sides). */
6832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         extrapolation_len = N+overlap;
6842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* We also apply fading if this is not the first loss. */
6852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         attenuation = MULT16_16_Q15(fade, decay);
6862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=j=0;i<extrapolation_len;i++,j++)
6872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
6882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_val16 tmp;
6892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            if (j >= pitch_index) {
6902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               j -= pitch_index;
6912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               attenuation = MULT16_16_Q15(attenuation, decay);
6922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
6932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            buf[DECODE_BUFFER_SIZE-N+i] =
6942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  SHL32(EXTEND32(MULT16_16_Q15(attenuation,
6952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                        exc[extrapolation_offset+j])), SIG_SHIFT);
6962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* Compute the energy of the previously decoded signal whose
6972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               excitation we're copying. */
6982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            tmp = ROUND16(
6992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
7002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  SIG_SHIFT);
7010c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            S1 += SHR32(MULT16_16(tmp, tmp), 10);
7022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
7032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
7042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_val16 lpc_mem[LPC_ORDER];
7052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* Copy the last decoded samples (prior to the overlap region) to
7062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               synthesis filter memory so we can have a continuous signal. */
7072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (i=0;i<LPC_ORDER;i++)
7082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               lpc_mem[i] = ROUND16(buf[DECODE_BUFFER_SIZE-N-1-i], SIG_SHIFT);
7092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* Apply the synthesis filter to convert the excitation back into
7102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               the signal domain. */
7112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
7122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
713c91ee5b5642fcc4969150f73d5f6848f88bf1638flim                  lpc_mem, st->arch);
7140c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#ifdef FIXED_POINT
7150c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim            for (i=0; i < extrapolation_len; i++)
7160c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim               buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT);
7170c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim#endif
7182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
7192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Check if the synthesis energy is higher than expected, which can
7212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            happen with the signal changes during our window. If so,
7222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            attenuate. */
7232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
7242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            opus_val32 S2=0;
7252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            for (i=0;i<extrapolation_len;i++)
7262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
7272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
7280c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim               S2 += SHR32(MULT16_16(tmp, tmp), 10);
7292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
7302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* This checks for an "explosion" in the synthesis. */
7312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
7322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            if (!(S1 > SHR32(S2,2)))
7332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
7342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            /* The float test is written this way to catch NaNs in the output
7352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               of the IIR filter at the same time. */
7362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            if (!(S1 > 0.2f*S2))
7372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
7382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
7392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               for (i=0;i<extrapolation_len;i++)
7402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  buf[DECODE_BUFFER_SIZE-N+i] = 0;
7412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            } else if (S1 < S2)
7422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            {
7432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
7442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               for (i=0;i<overlap;i++)
7452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               {
7462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  opus_val16 tmp_g = Q15ONE
7472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                        - MULT16_16_Q15(window[i], Q15ONE-ratio);
7482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  buf[DECODE_BUFFER_SIZE-N+i] =
7492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                        MULT16_32_Q15(tmp_g, buf[DECODE_BUFFER_SIZE-N+i]);
7502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               }
7512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               for (i=overlap;i<extrapolation_len;i++)
7522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               {
7532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                  buf[DECODE_BUFFER_SIZE-N+i] =
7542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian                        MULT16_32_Q15(ratio, buf[DECODE_BUFFER_SIZE-N+i]);
7552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               }
7562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            }
7572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
7582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Apply the pre-filter to the MDCT overlap for the next frame because
7602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            the post-filter will be re-applied in the decoder after the MDCT
7612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            overlap. */
7622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         comb_filter(etmp, buf+DECODE_BUFFER_SIZE,
7632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              st->postfilter_period, st->postfilter_period, overlap,
7642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian              -st->postfilter_gain, -st->postfilter_gain,
765c91ee5b5642fcc4969150f73d5f6848f88bf1638flim              st->postfilter_tapset, st->postfilter_tapset, NULL, 0, st->arch);
7662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         /* Simulate TDAC on the concealed audio so that it blends with the
7682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            MDCT of the next frame. */
7692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<overlap/2;i++)
7702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         {
7712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            buf[DECODE_BUFFER_SIZE+i] =
7722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               MULT16_32_Q15(window[i], etmp[overlap-1-i])
7732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               + MULT16_32_Q15(window[overlap-i-1], etmp[i]);
7742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         }
7752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      } while (++c<C);
7762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
7772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->loss_count = loss_count+1;
7792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
7802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
7812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
7822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
783c91ee5b5642fcc4969150f73d5f6848f88bf1638flimint celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data,
784c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum)
7852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
7862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int c, i, N;
7872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int spread_decision;
7882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 bits;
7892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ec_dec _dec;
790c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#ifdef NORM_ALIASING_HACK
791c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   celt_norm *X;
792c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#else
7932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(celt_norm, X);
794c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
7952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(int, fine_quant);
7962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(int, pulses);
7972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(int, cap);
7982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(int, offsets);
7992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(int, fine_priority);
8002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(int, tf_res);
8012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(unsigned char, collapse_masks);
8022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_sig *decode_mem[2];
8032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   celt_sig *out_syn[2];
8042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 *lpc;
8052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
8062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int shortBlocks;
8082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int isTransient;
8092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int intra_ener;
8102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const int CC = st->channels;
8112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int LM, M;
812c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int start;
813c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   int end;
8142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int effEnd;
8152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int codedBands;
8162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int alloc_trim;
8172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int postfilter_pitch;
8182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_val16 postfilter_gain;
8192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int intensity=0;
8202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int dual_stereo=0;
8212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 total_bits;
8222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 balance;
8232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   opus_int32 tell;
8242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int dynalloc_logp;
8252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int postfilter_tapset;
8262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int anti_collapse_rsv;
8272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int anti_collapse_on=0;
8282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int silence;
8292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int C = st->stream_channels;
8302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const OpusCustomMode *mode;
8312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int nbEBands;
8322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int overlap;
8332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   const opus_int16 *eBands;
8342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC_STACK;
8352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   mode = st->mode;
8372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   nbEBands = mode->nbEBands;
8382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   overlap = mode->overlap;
8392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   eBands = mode->eBands;
840c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   start = st->start;
841c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   end = st->end;
8422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   frame_size *= st->downsample;
8432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+overlap)*CC);
8452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   oldBandE = lpc+CC*LPC_ORDER;
8462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   oldLogE = oldBandE + 2*nbEBands;
8472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   oldLogE2 = oldLogE + 2*nbEBands;
8482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   backgroundLogE = oldLogE2  + 2*nbEBands;
8492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef CUSTOM_MODES
8512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (st->signalling && data!=NULL)
8522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int data0=data[0];
8542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Convert "standard mode" to Opus header */
8552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (mode->Fs==48000 && mode->shortMdctSize==120)
8562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
8572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         data0 = fromOpus(data0);
8582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (data0<0)
8592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            return OPUS_INVALID_PACKET;
8602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
861c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      st->end = end = IMAX(1, mode->effEBands-2*(data0>>5));
8622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      LM = (data0>>3)&0x3;
8632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      C = 1 + ((data0>>2)&0x1);
8642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      data++;
8652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      len--;
8662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (LM>mode->maxLM)
8672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return OPUS_INVALID_PACKET;
8682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (frame_size < mode->shortMdctSize<<LM)
8692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return OPUS_BUFFER_TOO_SMALL;
8702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      else
8712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         frame_size = mode->shortMdctSize<<LM;
8722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
8732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
8742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
8752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
8762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (LM=0;LM<=mode->maxLM;LM++)
8772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (mode->shortMdctSize<<LM==frame_size)
8782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            break;
8792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (LM>mode->maxLM)
8802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         return OPUS_BAD_ARG;
8812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
8822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   M=1<<LM;
8832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (len<0 || len>1275 || pcm==NULL)
8852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
8862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   N = M*mode->shortMdctSize;
888c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   c=0; do {
889c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+overlap);
890c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      out_syn[c] = decode_mem[c]+DECODE_BUFFER_SIZE-N;
891c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   } while (++c<CC);
8922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
893c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   effEnd = end;
8942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (effEnd > mode->effEBands)
8952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      effEnd = mode->effEBands;
8962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
8972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (data == NULL || len<=1)
8982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
899c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      celt_decode_lost(st, N, LM);
900c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
9012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      RESTORE_STACK;
9022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return frame_size/st->downsample;
9032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
905d03c373974c945b4b62b59b873522387418a2a3fFelicia Lim   /* Check if there are at least two packets received consecutively before
906d03c373974c945b4b62b59b873522387418a2a3fFelicia Lim    * turning on the pitch-based PLC */
907d03c373974c945b4b62b59b873522387418a2a3fFelicia Lim   st->skip_plc = st->loss_count != 0;
908d03c373974c945b4b62b59b873522387418a2a3fFelicia Lim
9092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (dec == NULL)
9102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      ec_dec_init(&_dec,(unsigned char*)data,len);
9122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      dec = &_dec;
9132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (C==1)
9162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<nbEBands;i++)
9182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldBandE[i]=MAX16(oldBandE[i],oldBandE[nbEBands+i]);
9192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   total_bits = len*8;
9222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tell = ec_tell(dec);
9232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (tell >= total_bits)
9252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      silence = 1;
9262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else if (tell==1)
9272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      silence = ec_dec_bit_logp(dec, 15);
9282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
9292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      silence = 0;
9302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (silence)
9312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Pretend we've read all the remaining bits */
9332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      tell = len*8;
9342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      dec->nbits_total+=tell-ec_tell(dec);
9352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   postfilter_gain = 0;
9382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   postfilter_pitch = 0;
9392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   postfilter_tapset = 0;
940c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   if (start==0 && tell+16 <= total_bits)
9412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if(ec_dec_bit_logp(dec, 1))
9432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
9442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int qg, octave;
9452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         octave = ec_dec_uint(dec, 6);
9462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
9472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         qg = ec_dec_bits(dec, 3);
9482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (ec_tell(dec)+2<=total_bits)
9492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
9502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         postfilter_gain = QCONST16(.09375f,15)*(qg+1);
9512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
9522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      tell = ec_tell(dec);
9532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (LM > 0 && tell+3 <= total_bits)
9562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      isTransient = ec_dec_bit_logp(dec, 3);
9582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      tell = ec_tell(dec);
9592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
9602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
9612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      isTransient = 0;
9622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (isTransient)
9642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      shortBlocks = M;
9652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   else
9662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      shortBlocks = 0;
9672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Decode the global flags (first symbols in the stream) */
9692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
9702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Get band energies */
971c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   unquant_coarse_energy(mode, start, end, oldBandE,
9722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         intra_ener, dec, C, LM);
9732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(tf_res, nbEBands, int);
975c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   tf_decode(start, end, isTransient, tf_res, LM, dec);
9762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tell = ec_tell(dec);
9782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   spread_decision = SPREAD_NORMAL;
9792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (tell+4 <= total_bits)
9802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
9812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(cap, nbEBands, int);
9832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   init_caps(mode,cap,LM,C);
9852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(offsets, nbEBands, int);
9872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
9882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   dynalloc_logp = 6;
9892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   total_bits<<=BITRES;
9902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   tell = ec_tell_frac(dec);
991c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   for (i=start;i<end;i++)
9922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
9932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int width, quanta;
9942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int dynalloc_loop_logp;
9952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      int boost;
9962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      width = C*(eBands[i+1]-eBands[i])<<LM;
9972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* quanta is 6 bits, but no more than 1 bit/sample
9982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         and no less than 1/8 bit/sample */
9992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
10002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      dynalloc_loop_logp = dynalloc_logp;
10012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      boost = 0;
10022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
10032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
10042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int flag;
10052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
10062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         tell = ec_tell_frac(dec);
10072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (!flag)
10082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            break;
10092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         boost += quanta;
10102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         total_bits -= quanta;
10112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         dynalloc_loop_logp = 1;
10122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
10132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      offsets[i] = boost;
10142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      /* Making dynalloc more likely */
10152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (boost>0)
10162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         dynalloc_logp = IMAX(2, dynalloc_logp-1);
10172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
10182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(fine_quant, nbEBands, int);
10202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   alloc_trim = tell+(6<<BITRES) <= total_bits ?
10212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         ec_dec_icdf(dec, trim_icdf, 7) : 5;
10222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   bits = (((opus_int32)len*8)<<BITRES) - ec_tell_frac(dec) - 1;
10242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
10252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   bits -= anti_collapse_rsv;
10262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(pulses, nbEBands, int);
10282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(fine_priority, nbEBands, int);
10292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1030c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   codedBands = compute_allocation(mode, start, end, offsets, cap,
10312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
10322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
10332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1034c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   unquant_fine_energy(mode, start, end, oldBandE, fine_quant, dec, C);
1035c91ee5b5642fcc4969150f73d5f6848f88bf1638flim
1036c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   c=0; do {
1037c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      OPUS_MOVE(decode_mem[c], decode_mem[c]+N, DECODE_BUFFER_SIZE-N+overlap/2);
1038c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   } while (++c<CC);
10392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* Decode fixed codebook */
10412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(collapse_masks, C*nbEBands, unsigned char);
1042c91ee5b5642fcc4969150f73d5f6848f88bf1638flim
1043c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#ifdef NORM_ALIASING_HACK
1044c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   /* This is an ugly hack that breaks aliasing rules and would be easily broken,
1045c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      but it saves almost 4kB of stack. */
1046c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   X = (celt_norm*)(out_syn[CC-1]+overlap/2);
1047c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#else
10482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(X, C*N, celt_norm);   /**< Interleaved normalised MDCTs */
1049c91ee5b5642fcc4969150f73d5f6848f88bf1638flim#endif
10502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1051c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
10522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
10530c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim         len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
10540c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim         st->arch, st->disable_inv);
10552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (anti_collapse_rsv > 0)
10572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
10582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      anti_collapse_on = ec_dec_bits(dec, 1);
10592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
10602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1061c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   unquant_energy_finalise(mode, start, end, oldBandE,
10622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
10632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (anti_collapse_on)
10652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      anti_collapse(mode, X, collapse_masks, LM, C, N,
1066c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng, st->arch);
10672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (silence)
10692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
10702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<C*nbEBands;i++)
10712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
10722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
10732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1074c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd,
1075c91ee5b5642fcc4969150f73d5f6848f88bf1638flim                  C, CC, isTransient, LM, st->downsample, silence, st->arch);
10762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   c=0; do {
10782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
10792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
10802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
10812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
1082c91ee5b5642fcc4969150f73d5f6848f88bf1638flim            mode->window, overlap, st->arch);
10832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      if (LM!=0)
10842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize,
10852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
1086c91ee5b5642fcc4969150f73d5f6848f88bf1638flim               mode->window, overlap, st->arch);
10872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
10882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } while (++c<CC);
10892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->postfilter_period_old = st->postfilter_period;
10902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->postfilter_gain_old = st->postfilter_gain;
10912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->postfilter_tapset_old = st->postfilter_tapset;
10922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->postfilter_period = postfilter_pitch;
10932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->postfilter_gain = postfilter_gain;
10942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->postfilter_tapset = postfilter_tapset;
10952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (LM!=0)
10962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
10972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->postfilter_period_old = st->postfilter_period;
10982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->postfilter_gain_old = st->postfilter_gain;
10992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->postfilter_tapset_old = st->postfilter_tapset;
11002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
11012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1102c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   if (C==1)
1103c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      OPUS_COPY(&oldBandE[nbEBands], oldBandE, nbEBands);
11042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   /* In case start or end were to change */
11062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (!isTransient)
11072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1108c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      opus_val16 max_background_increase;
1109c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands);
1110c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
1111c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      /* In normal circumstances, we only allow the noise floor to increase by
1112c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         up to 2.4 dB/second, but when we're in DTX, we allow up to 6 dB
1113c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         increase for each update.*/
1114c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      if (st->loss_count < 10)
1115c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         max_background_increase = M*QCONST16(0.001f,DB_SHIFT);
1116c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      else
1117c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         max_background_increase = QCONST16(1.f,DB_SHIFT);
11182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<2*nbEBands;i++)
1119c91ee5b5642fcc4969150f73d5f6848f88bf1638flim         backgroundLogE[i] = MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]);
11202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } else {
11212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (i=0;i<2*nbEBands;i++)
11222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]);
11232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
11242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   c=0; do
11252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
1126c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      for (i=0;i<start;i++)
11272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
11282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldBandE[c*nbEBands+i]=0;
11292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT);
11302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
1131c91ee5b5642fcc4969150f73d5f6848f88bf1638flim      for (i=end;i<nbEBands;i++)
11322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
11332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldBandE[c*nbEBands+i]=0;
11342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldLogE[c*nbEBands+i]=oldLogE2[c*nbEBands+i]=-QCONST16(28.f,DB_SHIFT);
11352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
11362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   } while (++c<2);
11372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->rng = dec->rng;
11382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1139c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   deemphasis(out_syn, pcm, N, CC, st->downsample, mode->preemph, st->preemph_memD, accum);
11402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   st->loss_count = 0;
11412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
11422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ec_tell(dec) > 8*len)
11432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_INTERNAL_ERROR;
11442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if(ec_get_error(dec))
11452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      st->error = 1;
11462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return frame_size/st->downsample;
11472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
11482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef CUSTOM_MODES
11512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifdef FIXED_POINT
11532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
11542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1155c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
11562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
11572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#ifndef DISABLE_FLOAT_API
11592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
11602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
11612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int j, ret, C, N;
11622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(opus_int16, out);
11632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC_STACK;
11642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (pcm==NULL)
11662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
11672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   C = st->channels;
11692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   N = frame_size;
11702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(out, C*N, opus_int16);
1172c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
11732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret>0)
11742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (j=0;j<C*ret;j++)
11752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[j]=out[j]*(1.f/32768.f);
11762bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
11782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return ret;
11792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
11802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif /* DISABLE_FLOAT_API */
11812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#else
11832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_custom_decode_float(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, float * OPUS_RESTRICT pcm, int frame_size)
11852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
1186c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL, 0);
11872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
11882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_custom_decode(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, int len, opus_int16 * OPUS_RESTRICT pcm, int frame_size)
11902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
11912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   int j, ret, C, N;
11922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   VARDECL(celt_sig, out);
11932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC_STACK;
11942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (pcm==NULL)
11962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      return OPUS_BAD_ARG;
11972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
11982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   C = st->channels;
11992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   N = frame_size;
12002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   ALLOC(out, C*N, celt_sig);
12012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
1202c91ee5b5642fcc4969150f73d5f6848f88bf1638flim   ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL, 0);
12032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
12042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   if (ret>0)
12052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      for (j=0;j<C*ret;j++)
12062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         pcm[j] = FLOAT2INT16 (out[j]);
12072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
12082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   RESTORE_STACK;
12092bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return ret;
12102bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
12112bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
12122bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif
12132bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian#endif /* CUSTOM_MODES */
12142bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
12152bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianint opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
12162bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian{
12172bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_list ap;
12182bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian
12192bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_start(ap, request);
12202bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   switch (request)
12212bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   {
12222bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case CELT_SET_START_BAND_REQUEST:
12232bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12242bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 value = va_arg(ap, opus_int32);
12252bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value<0 || value>=st->mode->nbEBands)
12262bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
12272bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         st->start = value;
12282bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case CELT_SET_END_BAND_REQUEST:
12312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 value = va_arg(ap, opus_int32);
12332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value<1 || value>st->mode->nbEBands)
12342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
12352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         st->end = value;
12362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case CELT_SET_CHANNELS_REQUEST:
12392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 value = va_arg(ap, opus_int32);
12412bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value<1 || value>2)
12422bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
12432bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         st->stream_channels = value;
12442bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12452bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12462bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case CELT_GET_AND_CLEAR_ERROR_REQUEST:
12472bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12482bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 *value = va_arg(ap, opus_int32*);
12492bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value==NULL)
12502bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
12512bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value=st->error;
12522bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         st->error = 0;
12532bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12542bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12552bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_GET_LOOKAHEAD_REQUEST:
12562bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12572bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 *value = va_arg(ap, opus_int32*);
12582bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value==NULL)
12592bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
12602bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value = st->overlap/st->downsample;
12612bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12622bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12632bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_RESET_STATE:
12642bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12652bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         int i;
12662bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_val16 *lpc, *oldBandE, *oldLogE, *oldLogE2;
12672bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*st->channels);
12682bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldBandE = lpc+st->channels*LPC_ORDER;
12692bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldLogE = oldBandE + 2*st->mode->nbEBands;
12702bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         oldLogE2 = oldLogE + 2*st->mode->nbEBands;
12712bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         OPUS_CLEAR((char*)&st->DECODER_RESET_START,
12722bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               opus_custom_decoder_get_size(st->mode, st->channels)-
12732bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian               ((char*)&st->DECODER_RESET_START - (char*)st));
12742bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         for (i=0;i<2*st->mode->nbEBands;i++)
12752bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT);
1276d03c373974c945b4b62b59b873522387418a2a3fFelicia Lim         st->skip_plc = 1;
12772bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12782bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12792bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_GET_PITCH_REQUEST:
12802bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12812bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 *value = va_arg(ap, opus_int32*);
12822bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value==NULL)
12832bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
12842bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value = st->postfilter_period;
12852bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12862bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12872bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case CELT_GET_MODE_REQUEST:
12882bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12892bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         const CELTMode ** value = va_arg(ap, const CELTMode**);
12902bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value==0)
12912bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
12922bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value=st->mode;
12932bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
12942bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
12952bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case CELT_SET_SIGNALLING_REQUEST:
12962bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
12972bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_int32 value = va_arg(ap, opus_int32);
12982bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         st->signalling = value;
12992bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
13002bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
13012bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      case OPUS_GET_FINAL_RANGE_REQUEST:
13022bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      {
13032bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         opus_uint32 * value = va_arg(ap, opus_uint32 *);
13042bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         if (value==0)
13052bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian            goto bad_arg;
13062bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         *value=st->rng;
13072bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      }
13082bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      break;
13090c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
13100c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      {
13110c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          opus_int32 value = va_arg(ap, opus_int32);
13120c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          if(value<0 || value>1)
13130c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          {
13140c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim             goto bad_arg;
13150c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          }
13160c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          st->disable_inv = value;
13170c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      }
13180c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      break;
13190c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
13200c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      {
13210c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          opus_int32 *value = va_arg(ap, opus_int32*);
13220c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          if (!value)
13230c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          {
13240c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim             goto bad_arg;
13250c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          }
13260c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim          *value = st->disable_inv;
13270c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      }
13280c2090c324e4f2ba2a8621c8b083559bab74c7c5Felicia Lim      break;
13292bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      default:
13302bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian         goto bad_request;
13312bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   }
13322bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_end(ap);
13332bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return OPUS_OK;
13342bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianbad_arg:
13352bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   va_end(ap);
13362bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian   return OPUS_BAD_ARG;
13372bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanianbad_request:
13382bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian      va_end(ap);
13392bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian  return OPUS_UNIMPLEMENTED;
13402bd8b54017b5320bc0c1df9bf86f4cdc9f8db242Vignesh Venkatasubramanian}
1341