1885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited 2885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Written by Jean-Marc Valin and Koen Vos */ 3885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org/* 4885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Redistribution and use in source and binary forms, with or without 5885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org modification, are permitted provided that the following conditions 6885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org are met: 7885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 8885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org - Redistributions of source code must retain the above copyright 9885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org notice, this list of conditions and the following disclaimer. 10885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 11885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org - Redistributions in binary form must reproduce the above copyright 12885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org notice, this list of conditions and the following disclaimer in the 13885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org documentation and/or other materials provided with the distribution. 14885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 15885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 19885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 22885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org*/ 27885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 28885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef HAVE_CONFIG_H 293c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com# include "config.h" 30885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 31885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 32885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifndef OPUS_BUILD 333c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com# error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details." 343c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com#endif 353c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com 363c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com#if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__) 373c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com# pragma message "You appear to be compiling without optimization, if so opus will be very slow." 38885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 39885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 40885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include <stdarg.h> 41885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "celt.h" 42885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "opus.h" 43885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "entdec.h" 44885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "modes.h" 45885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "API.h" 46885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "stack_alloc.h" 47885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "float_cast.h" 48885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "opus_private.h" 49885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "os_support.h" 50885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "structs.h" 51885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "define.h" 52885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#include "mathops.h" 53e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#include "cpu_support.h" 54885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 55885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstruct OpusDecoder { 56885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int celt_dec_offset; 57885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int silk_dec_offset; 58885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int channels; 59885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 Fs; /** Sampling rate (at the API level) */ 60885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_DecControlStruct DecControl; 61885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int decode_gain; 62885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 63885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Everything beyond this point gets cleared on a reset */ 64885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#define OPUS_DECODER_RESET_START stream_channels 65885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int stream_channels; 66885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 67885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int bandwidth; 68885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int mode; 69885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int prev_mode; 70885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int frame_size; 71885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int prev_redundancy; 726b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org int last_packet_duration; 73e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifndef FIXED_POINT 74e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_val16 softclip_mem[2]; 75e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif 76885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 77885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_uint32 rangeFinal; 78885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org}; 79885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 80885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT 813c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.comstatic OPUS_INLINE opus_int16 SAT16(opus_int32 x) { 82885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x; 83885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 84885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 85885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 86885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 87885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decoder_get_size(int channels) 88885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 89885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int silkDecSizeBytes, celtDecSizeBytes; 90885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ret; 91885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (channels<1 || channels > 2) 92885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 93885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ret = silk_Get_Decoder_Size( &silkDecSizeBytes ); 94885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if(ret) 95885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 0; 96885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silkDecSizeBytes = align(silkDecSizeBytes); 97885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celtDecSizeBytes = celt_decoder_get_size(channels); 98885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes; 99885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 100885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 101885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels) 102885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 103885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void *silk_dec; 104885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org CELTDecoder *celt_dec; 105885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ret, silkDecSizeBytes; 106885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 107885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000) 108885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org || (channels!=1&&channels!=2)) 109885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BAD_ARG; 110885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 111885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org OPUS_CLEAR((char*)st, opus_decoder_get_size(channels)); 112885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Initialize SILK encoder */ 113885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ret = silk_Get_Decoder_Size(&silkDecSizeBytes); 114885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (ret) 115885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_INTERNAL_ERROR; 116885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 117885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silkDecSizeBytes = align(silkDecSizeBytes); 118885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->silk_dec_offset = align(sizeof(OpusDecoder)); 119885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes; 120885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_dec = (char*)st+st->silk_dec_offset; 121885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); 122885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->stream_channels = st->channels = channels; 123885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 124885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->Fs = Fs; 125885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.API_sampleRate = st->Fs; 126885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.nChannelsAPI = st->channels; 127885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 128885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Reset decoder */ 129885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ret = silk_InitDecoder( silk_dec ); 130885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if(ret)return OPUS_INTERNAL_ERROR; 131885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 132885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Initialize CELT decoder */ 133885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ret = celt_decoder_init(celt_dec, Fs, channels); 134885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR; 135885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 136885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0)); 137885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 138885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->prev_mode = 0; 139885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->frame_size = Fs/400; 140885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_OK; 141885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 142885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 143885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgOpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error) 144885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 145885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ret; 146885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org OpusDecoder *st; 147885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000) 148885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org || (channels!=1&&channels!=2)) 149885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 150885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (error) 151885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *error = OPUS_BAD_ARG; 152885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return NULL; 153885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 154885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels)); 155885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (st == NULL) 156885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 157885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (error) 158885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *error = OPUS_ALLOC_FAIL; 159885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return NULL; 160885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 161885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ret = opus_decoder_init(st, Fs, channels); 162885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (error) 163885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *error = ret; 164885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (ret != OPUS_OK) 165885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 166885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_free(st); 167885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st = NULL; 168885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 169885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return st; 170885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 171885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 172885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic void smooth_fade(const opus_val16 *in1, const opus_val16 *in2, 173885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val16 *out, int overlap, int channels, 174885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_val16 *window, opus_int32 Fs) 175885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 176885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int i, c; 177885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int inc = 48000/Fs; 178885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (c=0;c<channels;c++) 179885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 180885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<overlap;i++) 181885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 182885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val16 w = MULT16_16_Q15(window[i*inc], window[i*inc]); 183885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]), 184885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org Q15ONE-w, in1[i*channels+c]), 15); 185885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 186885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 187885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 188885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 189885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic int opus_packet_get_mode(const unsigned char *data) 190885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 191885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int mode; 192885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (data[0]&0x80) 193885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 194885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mode = MODE_CELT_ONLY; 195885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if ((data[0]&0x60) == 0x60) 196885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 197885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mode = MODE_HYBRID; 198885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 199885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mode = MODE_SILK_ONLY; 200885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 201885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return mode; 202885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 203885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 204885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgstatic int opus_decode_frame(OpusDecoder *st, const unsigned char *data, 205885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) 206885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 207885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void *silk_dec; 208885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org CELTDecoder *celt_dec; 209885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int i, silk_ret=0, celt_ret=0; 210885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ec_dec dec; 211885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 silk_frame_size; 212e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int pcm_silk_size; 213885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org VARDECL(opus_int16, pcm_silk); 214e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int pcm_transition_silk_size; 215e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org VARDECL(opus_val16, pcm_transition_silk); 216e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int pcm_transition_celt_size; 217e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org VARDECL(opus_val16, pcm_transition_celt); 218e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_val16 *pcm_transition; 219e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org int redundant_audio_size; 220885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org VARDECL(opus_val16, redundant_audio); 221885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 222885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int audiosize; 223885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int mode; 224885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int transition=0; 225885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int start_band; 226885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int redundancy=0; 227885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int redundancy_bytes = 0; 228885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int celt_to_silk=0; 229885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int c; 230885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int F2_5, F5, F10, F20; 231885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const opus_val16 *window; 232885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_uint32 redundant_rng = 0; 233885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ALLOC_STACK; 234885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 235885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_dec = (char*)st+st->silk_dec_offset; 236885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); 237885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org F20 = st->Fs/50; 238885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org F10 = F20>>1; 239885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org F5 = F10>>1; 240885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org F2_5 = F5>>1; 241885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (frame_size < F2_5) 242885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 243885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 244885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BUFFER_TOO_SMALL; 245885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 246660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org /* Limit frame_size to avoid excessive stack allocations. */ 247660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org frame_size = IMIN(frame_size, st->Fs/25*3); 248885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */ 249885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (len<=1) 250885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 251885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org data = NULL; 252885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* In that case, don't conceal more than what the ToC says */ 253885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org frame_size = IMIN(frame_size, st->frame_size); 254885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 255885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (data != NULL) 256885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 257885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = st->frame_size; 258885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org mode = st->mode; 259885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ec_dec_init(&dec,(unsigned char*)data,len); 260885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 261885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = frame_size; 2623c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com mode = st->prev_mode; 263885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 2643c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if (mode == 0) 265885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 266885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* If we haven't got any packet yet, all we can do is return zeros */ 267885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<audiosize*st->channels;i++) 268885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = 0; 269885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 270885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return audiosize; 271885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 272885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 2733c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT), 2743c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com 10, or 20 (e.g. 12.5 or 30 ms). */ 2753c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if (audiosize > F20) 2763c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com { 2773c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com do { 2783c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0); 2793c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if (ret<0) 2803c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com { 2813c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com RESTORE_STACK; 2823c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com return ret; 2833c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com } 2843c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com pcm += ret*st->channels; 2853c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com audiosize -= ret; 2863c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com } while (audiosize > 0); 2873c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com RESTORE_STACK; 2883c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com return frame_size; 2893c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com } else if (audiosize < F20) 2903c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com { 2913c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if (audiosize > F10) 2923c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com audiosize = F10; 2933c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10) 2943c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com audiosize = F5; 2953c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com } 2963c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com } 297885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 2983c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com pcm_transition_silk_size = ALLOC_NONE; 2993c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com pcm_transition_celt_size = ALLOC_NONE; 300885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (data!=NULL && st->prev_mode > 0 && ( 301885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy) 302885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ) 303885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ) 304885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 305885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org transition = 1; 306e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /* Decide where to allocate the stack memory for pcm_transition */ 307885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (mode == MODE_CELT_ONLY) 308e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org pcm_transition_celt_size = F5*st->channels; 309e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org else 310e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org pcm_transition_silk_size = F5*st->channels; 311e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 312e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16); 313e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (transition && mode == MODE_CELT_ONLY) 314e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 315e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org pcm_transition = pcm_transition_celt; 316e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); 317885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 318885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (audiosize > frame_size) 319885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 320885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/ 321885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 322885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BAD_ARG; 323885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 324885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org frame_size = audiosize; 325885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 326885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 327e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /* Don't allocate any memory when in CELT-only mode */ 3283c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com pcm_silk_size = (mode != MODE_CELT_ONLY) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE; 329e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ALLOC(pcm_silk, pcm_silk_size, opus_int16); 330885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 331885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* SILK processing */ 332885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (mode != MODE_CELT_ONLY) 333885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 334885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int lost_flag, decoded_samples; 335885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int16 *pcm_ptr = pcm_silk; 336885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 337885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (st->prev_mode==MODE_CELT_ONLY) 338885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_InitDecoder( silk_dec ); 339885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 340885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* The SILK PLC cannot produce frames of less than 10 ms */ 341885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs); 342885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 343885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (data != NULL) 344885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 345885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.nChannelsInternal = st->stream_channels; 346885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( mode == MODE_SILK_ONLY ) { 347885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) { 348885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.internalSampleRate = 8000; 349885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) { 350885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.internalSampleRate = 12000; 351885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) { 352885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.internalSampleRate = 16000; 353885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 354885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.internalSampleRate = 16000; 355885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_assert( 0 ); 356885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 357885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 358885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Hybrid mode */ 359885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->DecControl.internalSampleRate = 16000; 360885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 361885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 362885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 363885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org lost_flag = data == NULL ? 1 : 2 * decode_fec; 364885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org decoded_samples = 0; 365885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org do { 366885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Call SILK decoder */ 367885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int first_frame = decoded_samples == 0; 368885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_ret = silk_Decode( silk_dec, &st->DecControl, 369885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size ); 370885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if( silk_ret ) { 371885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (lost_flag) { 372885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* PLC failure should not be fatal */ 373885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_frame_size = frame_size; 374885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<frame_size*st->channels;i++) 375885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm_ptr[i] = 0; 376885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 377885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 3783c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com return OPUS_INTERNAL_ERROR; 379885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 380885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 381885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm_ptr += silk_frame_size * st->channels; 382885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org decoded_samples += silk_frame_size; 383885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } while( decoded_samples < frame_size ); 384885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 385885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 386885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org start_band = 0; 387885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL 388885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len) 389885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 390885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Check if we have a redundant 0-8 kHz band */ 391885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (mode == MODE_HYBRID) 392885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org redundancy = ec_dec_bit_logp(&dec, 12); 393885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 394885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org redundancy = 1; 395885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (redundancy) 396885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 397885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_to_silk = ec_dec_bit_logp(&dec, 1); 398885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* redundancy_bytes will be at least two, in the non-hybrid 399885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case due to the ec_tell() check above */ 400885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org redundancy_bytes = mode==MODE_HYBRID ? 401885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org (opus_int32)ec_dec_uint(&dec, 256)+2 : 402885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org len-((ec_tell(&dec)+7)>>3); 403885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org len -= redundancy_bytes; 404885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* This is a sanity check. It should never happen for a valid 405885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org packet, so the exact behaviour is not normative. */ 406885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (len*8 < ec_tell(&dec)) 407885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 408885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org len = 0; 409885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org redundancy_bytes = 0; 410885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org redundancy = 0; 411885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 412885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Shrink decoder because of raw bits */ 413885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org dec.storage -= redundancy_bytes; 414885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 415885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 416885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (mode != MODE_CELT_ONLY) 417885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org start_band = 17; 418885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 419885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 420885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int endband=21; 421885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 422885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org switch(st->bandwidth) 423885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 424885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_BANDWIDTH_NARROWBAND: 425885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org endband = 13; 426885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 427885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_BANDWIDTH_MEDIUMBAND: 428885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_BANDWIDTH_WIDEBAND: 429885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org endband = 17; 430885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 431885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_BANDWIDTH_SUPERWIDEBAND: 432885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org endband = 19; 433885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 434885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_BANDWIDTH_FULLBAND: 435885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org endband = 21; 436885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 437885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 438885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)); 439885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)); 440885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 441885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 442885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (redundancy) 443e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 444885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org transition = 0; 4453c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com pcm_transition_silk_size=ALLOC_NONE; 446e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 447e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 448e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16); 449885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 450885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (transition && mode != MODE_CELT_ONLY) 451e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 452e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org pcm_transition = pcm_transition_silk; 453885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); 454e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 455e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 456e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org /* Only allocation memory for redundancy if/when needed */ 4573c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE; 458e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ALLOC(redundant_audio, redundant_audio_size, opus_val16); 459885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 460885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* 5 ms redundant frame for CELT->SILK*/ 461885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (redundancy && celt_to_silk) 462885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 463885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); 464885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, 465885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org redundant_audio, F5, NULL); 466885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); 467885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 468885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 469885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* MUST be after PLC */ 470885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)); 471885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 472885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (mode != MODE_SILK_ONLY) 473885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 474885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int celt_frame_size = IMIN(F20, frame_size); 475885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Make sure to discard any previous CELT state */ 476885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy) 477885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); 478885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Decode CELT */ 479885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data, 480885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org len, pcm, celt_frame_size, &dec); 481885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 482885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org unsigned char silence[2] = {0xFF, 0xFF}; 483885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<frame_size*st->channels;i++) 484885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = 0; 485885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* For hybrid -> SILK transitions, we let the CELT MDCT 486885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org do a fade-out by decoding a silence frame */ 487885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) ) 488885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 489885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); 490885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL); 491885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 492885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 493885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 494885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (mode != MODE_CELT_ONLY) 495885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 496885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT 497885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<frame_size*st->channels;i++) 498885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = SAT16(pcm[i] + pcm_silk[i]); 499885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#else 500885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<frame_size*st->channels;i++) 501885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]); 502885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 503885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 504885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 505885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 506885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org const CELTMode *celt_mode; 507885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)); 508885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org window = celt_mode->window; 509885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 510885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 511885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* 5 ms redundant frame for SILK->CELT */ 512885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (redundancy && !celt_to_silk) 513885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 514885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); 515885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); 516885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 517885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL); 518885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); 519885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5, 520885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs); 521885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 522885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (redundancy && celt_to_silk) 523885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 524885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (c=0;c<st->channels;c++) 525885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 526885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<F2_5;i++) 527885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[st->channels*i+c] = redundant_audio[st->channels*i+c]; 528885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 529885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5, 530885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs); 531885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 532885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (transition) 533885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 534885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (audiosize >= F5) 535885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 536885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<st->channels*F2_5;i++) 537885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = pcm_transition[i]; 538885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5, 539885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm+st->channels*F2_5, F2_5, 540885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->channels, window, st->Fs); 541885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 542885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Not enough time to do a clean transition, but we do it anyway 543885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org This will not preserve amplitude perfectly and may introduce 544885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org a bit of temporal aliasing, but it shouldn't be too bad and 545885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org that's pretty much the best we can do. In any case, generating this 546885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org transition it pretty silly in the first place */ 547885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org smooth_fade(pcm_transition, pcm, 548885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm, F2_5, 549885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->channels, window, st->Fs); 550885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 551885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 552885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 553885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if(st->decode_gain) 554885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 555885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 gain; 556885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain)); 557885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<frame_size*st->channels;i++) 558885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 559885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_val32 x; 560885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org x = MULT16_32_P16(pcm[i],gain); 561885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = SATURATE(x, 32767); 562885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 563885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 564885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 565885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (len <= 1) 566885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->rangeFinal = 0; 567885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 568885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->rangeFinal = dec.rng ^ redundant_rng; 569885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 570885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->prev_mode = mode; 571885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->prev_redundancy = redundancy && !celt_to_silk; 572e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 573e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (celt_ret>=0) 574e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 575e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels)) 576e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org OPUS_PRINT_INT(audiosize); 577e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 578e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org 579885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 580885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return celt_ret < 0 ? celt_ret : audiosize; 581885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 582885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 583885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 584885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decode_native(OpusDecoder *st, const unsigned char *data, 585885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec, 5863c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com int self_delimited, opus_int32 *packet_offset, int soft_clip) 587885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 588885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int i, nb_samples; 589885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int count, offset; 590885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org unsigned char toc; 5916b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels; 592885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* 48 x 2.5 ms = 120 ms */ 593e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_int16 size[48]; 594885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (decode_fec<0 || decode_fec>1) 595885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BAD_ARG; 5966b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org /* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */ 5976b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0) 5986b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org return OPUS_BAD_ARG; 599885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (len==0 || data==NULL) 6006b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org { 6016b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org int pcm_count=0; 6026b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org do { 6036b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org int ret; 604e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0); 6056b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org if (ret<0) 6066b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org return ret; 6076b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org pcm_count += ret; 6086b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org } while (pcm_count < frame_size); 609e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org celt_assert(pcm_count == frame_size); 610e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels)) 611e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org OPUS_PRINT_INT(pcm_count); 6126b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->last_packet_duration = pcm_count; 6136b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org return pcm_count; 6146b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org } else if (len<0) 615885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BAD_ARG; 616885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 6176b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org packet_mode = opus_packet_get_mode(data); 6186b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org packet_bandwidth = opus_packet_get_bandwidth(data); 6196b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs); 6206b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org packet_stream_channels = opus_packet_get_nb_channels(data); 621885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 6223c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL, 6233c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com size, &offset, packet_offset); 6243c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if (count<0) 6253c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com return count; 6266b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org 6276b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org data += offset; 6286b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org 6296b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org if (decode_fec) 6306b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org { 6316b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org int duration_copy; 6326b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org int ret; 6336b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org /* If no FEC can be present, run the PLC (recursive call) */ 634e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY) 635e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip); 6366b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org /* Otherwise, run the PLC on everything except the size for which we might have FEC */ 6376b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org duration_copy = st->last_packet_duration; 638e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (frame_size-packet_frame_size!=0) 6396b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org { 640e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip); 641e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (ret<0) 642e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 643e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org st->last_packet_duration = duration_copy; 644e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return ret; 645e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 646e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org celt_assert(ret==frame_size-packet_frame_size); 6476b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org } 6486b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org /* Complete with FEC */ 6496b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->mode = packet_mode; 6506b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->bandwidth = packet_bandwidth; 6516b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->frame_size = packet_frame_size; 6526b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->stream_channels = packet_stream_channels; 6536b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size), 6546b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org packet_frame_size, 1); 6556b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org if (ret<0) 6566b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org return ret; 657e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org else { 658e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels)) 659e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org OPUS_PRINT_INT(frame_size); 660e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org st->last_packet_duration = frame_size; 661e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return frame_size; 662e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 6636b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org } 664885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 6656b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org if (count*packet_frame_size > frame_size) 666885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BUFFER_TOO_SMALL; 6676b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org 6686b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org /* Update the state as the last step to avoid updating it on an invalid packet */ 6696b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->mode = packet_mode; 6706b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->bandwidth = packet_bandwidth; 6716b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->frame_size = packet_frame_size; 6726b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->stream_channels = packet_stream_channels; 6736b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org 674885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nb_samples=0; 675885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<count;i++) 676885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 677885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ret; 678e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0); 679885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (ret<0) 680885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return ret; 681e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org celt_assert(ret==packet_frame_size); 682885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org data += size[i]; 683885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org nb_samples += ret; 684885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 6856b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org st->last_packet_duration = nb_samples; 686e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels)) 687e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org OPUS_PRINT_INT(nb_samples); 688e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#ifndef FIXED_POINT 689e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (soft_clip) 690e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem); 691e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org else 692e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org st->softclip_mem[0]=st->softclip_mem[1]=0; 693e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org#endif 694885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return nb_samples; 695885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 696885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 697885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifdef FIXED_POINT 698885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 699885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decode(OpusDecoder *st, const unsigned char *data, 700885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) 701885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 7023c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if(frame_size<=0) 7033c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com return OPUS_BAD_ARG; 704e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); 705885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 706885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 707885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#ifndef DISABLE_FLOAT_API 708885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decode_float(OpusDecoder *st, const unsigned char *data, 709885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 len, float *pcm, int frame_size, int decode_fec) 710885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 711885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org VARDECL(opus_int16, out); 712885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ret, i; 713885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ALLOC_STACK; 714885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 7153c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if(frame_size<=0) 7163c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com { 7173c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com RESTORE_STACK; 7183c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com return OPUS_BAD_ARG; 7193c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com } 720885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ALLOC(out, frame_size*st->channels, opus_int16); 721885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 722e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0); 723885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (ret > 0) 724885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 725885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<ret*st->channels;i++) 726885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = (1.f/32768.f)*(out[i]); 727885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 728885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 729885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return ret; 730885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 731885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 732885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 733885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 734885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#else 735885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decode(OpusDecoder *st, const unsigned char *data, 736885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec) 737885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 738885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org VARDECL(float, out); 739885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ret, i; 740885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ALLOC_STACK; 741885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 7423c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if(frame_size<=0) 743885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 744885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 745885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BAD_ARG; 746885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 747885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 748885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ALLOC(out, frame_size*st->channels, float); 749885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 750e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1); 751885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (ret > 0) 752885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 753885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org for (i=0;i<ret*st->channels;i++) 754885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org pcm[i] = FLOAT2INT16(out[i]); 755885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 756885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org RESTORE_STACK; 757885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return ret; 758885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 759885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 760885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decode_float(OpusDecoder *st, const unsigned char *data, 761885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) 762885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 7633c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com if(frame_size<=0) 7643c3902f0ac13428394f14f78f0fab05ef3468d69tlegrand@google.com return OPUS_BAD_ARG; 765e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0); 766885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 767885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 768885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org#endif 769885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 770885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_decoder_ctl(OpusDecoder *st, int request, ...) 771885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 772885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int ret = OPUS_OK; 773885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org va_list ap; 774885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org void *silk_dec; 775885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org CELTDecoder *celt_dec; 776885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 777885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_dec = (char*)st+st->silk_dec_offset; 778885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); 779885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 780885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 781885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org va_start(ap, request); 782885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 783885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org switch (request) 784885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 785885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_GET_BANDWIDTH_REQUEST: 786885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 787885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *value = va_arg(ap, opus_int32*); 788e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (!value) 789e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 790e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org goto bad_arg; 791e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 792885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *value = st->bandwidth; 793885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 794885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 795885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_GET_FINAL_RANGE_REQUEST: 796885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 797885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_uint32 *value = va_arg(ap, opus_uint32*); 798e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (!value) 799e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 800e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org goto bad_arg; 801e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 802885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *value = st->rangeFinal; 803885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 804885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 805885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_RESET_STATE: 806885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 807885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START, 808885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org sizeof(OpusDecoder)- 809885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ((char*)&st->OPUS_DECODER_RESET_START - (char*)st)); 810885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 811885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); 812885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org silk_InitDecoder( silk_dec ); 813885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->stream_channels = st->channels; 814885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->frame_size = st->Fs/400; 815885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 816885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 817660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org case OPUS_GET_SAMPLE_RATE_REQUEST: 818660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org { 819660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org opus_int32 *value = va_arg(ap, opus_int32*); 820e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (!value) 821660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org { 822e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org goto bad_arg; 823660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org } 824660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org *value = st->Fs; 825660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org } 826660e25f9ad9e0b421241dcf675c6883fecb859cdsergeyu@chromium.org break; 827885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_GET_PITCH_REQUEST: 828885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 829885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *value = va_arg(ap, opus_int32*); 830e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (!value) 831885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 832e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org goto bad_arg; 833885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 834885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (st->prev_mode == MODE_CELT_ONLY) 835885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value)); 836885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 837885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *value = st->DecControl.prevPitchLag; 838885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 839885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 840885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_GET_GAIN_REQUEST: 841885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 842885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 *value = va_arg(ap, opus_int32*); 843e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (!value) 844885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 845e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org goto bad_arg; 846885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 847885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org *value = st->decode_gain; 848885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 849885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 850885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org case OPUS_SET_GAIN_REQUEST: 851885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 852885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 value = va_arg(ap, opus_int32); 853885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (value<-32768 || value>32767) 854885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 855e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org goto bad_arg; 856885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 857885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org st->decode_gain = value; 858885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 859885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 8606b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org case OPUS_GET_LAST_PACKET_DURATION_REQUEST: 8616b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org { 8626b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org opus_uint32 *value = va_arg(ap, opus_uint32*); 863e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org if (!value) 864e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org { 865e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org goto bad_arg; 866e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org } 8676b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org *value = st->last_packet_duration; 8686b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org } 8696b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org break; 870885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org default: 871885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/ 872885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org ret = OPUS_UNIMPLEMENTED; 873885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org break; 874885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 875885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 876885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org va_end(ap); 877885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return ret; 878e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.orgbad_arg: 879e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org va_end(ap); 880e3ea049fcaee2247e45f0ce793d4313babb4ef69tlegrand@chromium.org return OPUS_BAD_ARG; 881885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 882885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 883885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgvoid opus_decoder_destroy(OpusDecoder *st) 884885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 885885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_free(st); 886885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 887885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 888885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 889885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_packet_get_bandwidth(const unsigned char *data) 890885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 891885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int bandwidth; 892885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (data[0]&0x80) 893885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 894885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org bandwidth = OPUS_BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3); 895885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) 896885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org bandwidth = OPUS_BANDWIDTH_NARROWBAND; 897885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if ((data[0]&0x60) == 0x60) 898885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 899885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org bandwidth = (data[0]&0x10) ? OPUS_BANDWIDTH_FULLBAND : 900885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org OPUS_BANDWIDTH_SUPERWIDEBAND; 901885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 902885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org bandwidth = OPUS_BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3); 903885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 904885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return bandwidth; 905885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 906885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 907885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_packet_get_samples_per_frame(const unsigned char *data, 908885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org opus_int32 Fs) 909885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 910885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int audiosize; 911885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (data[0]&0x80) 912885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 913885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = ((data[0]>>3)&0x3); 914885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = (Fs<<audiosize)/400; 915885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else if ((data[0]&0x60) == 0x60) 916885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org { 917885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = (data[0]&0x08) ? Fs/50 : Fs/100; 918885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } else { 919885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = ((data[0]>>3)&0x3); 920885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (audiosize == 3) 921885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = Fs*60/1000; 922885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 923885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org audiosize = (Fs<<audiosize)/100; 924885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org } 925885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return audiosize; 926885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 927885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 928885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_packet_get_nb_channels(const unsigned char *data) 929885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 930885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return (data[0]&0x4) ? 2 : 1; 931885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 932885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 933885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.orgint opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) 934885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 935885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int count; 936885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (len<1) 937885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_BAD_ARG; 938885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org count = packet[0]&0x3; 939885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (count==0) 940885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 1; 941885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else if (count!=3) 942885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return 2; 943885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else if (len<2) 944885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_INVALID_PACKET; 945885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 946885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return packet[1]&0x3F; 947885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 948885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 9496b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.orgint opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, 9506b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org opus_int32 Fs) 951885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org{ 952885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int samples; 953885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org int count = opus_packet_get_nb_frames(packet, len); 954885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 955885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org if (count<0) 956885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return count; 957885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org 9586b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org samples = count*opus_packet_get_samples_per_frame(packet, Fs); 959885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org /* Can't have more than 120 ms */ 9606b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org if (samples*25 > Fs*3) 961885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return OPUS_INVALID_PACKET; 962885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org else 963885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org return samples; 964885f2ff5a7a7d6a73432d26a6c0ae9147e6b452sergeyu@chromium.org} 9656b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org 9666b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.orgint opus_decoder_get_nb_samples(const OpusDecoder *dec, 9676b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org const unsigned char packet[], opus_int32 len) 9686b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org{ 9696b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org return opus_packet_get_nb_samples(packet, len, dec->Fs); 9706b6bee25314cfac02cc555cddedb9680c63a26d6sergeyu@chromium.org} 971