blob: 0928a0423d7024ae33f9492ace9dd20e7b24493f [file] [log] [blame]
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04001/* Copyright (c) 2007-2008 CSIRO
Jean-Marc Valin190b7822010-08-27 15:03:20 -04002 Copyright (c) 2007-2010 Xiph.Org Foundation
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04003 Copyright (c) 2008 Gregory Maxwell
Jean-Marc Valin8b2ff0d2009-10-17 21:40:10 -04004 Written by Jean-Marc Valin and Gregory Maxwell */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11005/*
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04009
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110010 - Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
Gregory Maxwell71d39ad2011-07-30 00:00:29 -040012
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110013 - Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
Gregory Maxwell71d39ad2011-07-30 00:00:29 -040016
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110017 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
21 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
Jean-Marc Valin02fa9132008-02-20 12:09:29 +110030#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
Jean-Marc Valin8600f692008-02-29 15:14:12 +110034#define CELT_C
35
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +110036#include "os_support.h"
Jean-Marc Valinf02ba112007-11-30 01:10:42 +110037#include "mdct.h"
38#include <math.h>
Jean-Marc Valin013c31d2007-11-30 11:36:46 +110039#include "celt.h"
Jean-Marc Valin14191b32007-11-30 12:15:49 +110040#include "pitch.h"
Jean-Marc Valin991c0f02007-11-30 16:07:46 +110041#include "bands.h"
Jean-Marc Valinecb36a32007-12-05 01:31:49 +110042#include "modes.h"
Jean-Marc Valin6238bc02008-01-28 22:28:54 +110043#include "entcode.h"
Jean-Marc Valin98d2a492007-12-07 22:46:47 +110044#include "quant_bands.h"
Jean-Marc Valin4fbd18d2008-01-17 14:07:55 +110045#include "rate.h"
Jean-Marc Valinc7e0b762008-03-16 07:55:29 +110046#include "stack_alloc.h"
Jean-Marc Valine4aeb472008-06-29 12:06:05 +100047#include "mathops.h"
Jean-Marc Valind9b95652008-08-31 23:34:47 -040048#include "float_cast.h"
Jean-Marc Valinb6f90612008-10-05 22:39:13 -040049#include <stdarg.h>
Jean-Marc Valin2779df72011-10-04 13:26:53 -040050#include "celt_lpc.h"
Jean-Marc Valineafd8a72011-01-23 00:24:45 -050051#include "vq.h"
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -050052
Ralph Gilesb0f4e902011-09-07 13:16:29 -070053#ifndef OPUS_VERSION
54#define OPUS_VERSION "unknown"
55#endif
56
Gregory Maxwellafc8d532011-09-28 15:13:26 -040057#ifdef CUSTOM_MODES
58#define OPUS_CUSTOM_NOSTATIC
59#else
60#define OPUS_CUSTOM_NOSTATIC static inline
61#endif
62
Timothy B. Terriberry845dfa12011-01-02 16:53:28 -080063static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0};
64/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */
65static const unsigned char spread_icdf[4] = {25, 23, 2, 0};
Jean-Marc Valin4b087df2010-11-30 21:08:31 -050066
Jean-Marc Valin2ce5c632011-01-17 20:50:18 -050067static const unsigned char tapset_icdf[3]={2,1,0};
68
Gregory Maxwellfd17eab2011-10-04 03:31:45 -040069#ifdef CUSTOM_MODES
Jean-Marc Valind6bf19d2011-03-21 07:06:09 -040070static const unsigned char toOpusTable[20] = {
71 0xE0, 0xE8, 0xF0, 0xF8,
72 0xC0, 0xC8, 0xD0, 0xD8,
73 0xA0, 0xA8, 0xB0, 0xB8,
74 0x00, 0x00, 0x00, 0x00,
75 0x80, 0x88, 0x90, 0x98,
76};
77
78static const unsigned char fromOpusTable[16] = {
79 0x80, 0x88, 0x90, 0x98,
80 0x40, 0x48, 0x50, 0x58,
81 0x20, 0x28, 0x30, 0x38,
82 0x00, 0x08, 0x10, 0x18
83};
84
85static inline int toOpus(unsigned char c)
86{
87 int ret=0;
88 if (c<0xA0)
89 ret = toOpusTable[c>>3];
90 if (ret == 0)
91 return -1;
92 else
93 return ret|(c&0x7);
94}
95
96static inline int fromOpus(unsigned char c)
97{
98 if (c<0x80)
99 return -1;
100 else
101 return fromOpusTable[(c>>3)-16] | (c&0x7);
102}
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400103#endif /*CUSTOM_MODES*/
Jean-Marc Valind6bf19d2011-03-21 07:06:09 -0400104
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400105#define COMBFILTER_MAXPERIOD 1024
Jean-Marc Valind1212602011-01-25 13:11:36 -0500106#define COMBFILTER_MINPERIOD 15
Jean-Marc Valin6bf04622010-09-30 10:16:22 -0400107
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400108static int resampling_factor(opus_int32 rate)
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500109{
110 int ret;
111 switch (rate)
112 {
113 case 48000:
114 ret = 1;
115 break;
116 case 24000:
117 ret = 2;
118 break;
119 case 16000:
120 ret = 3;
121 break;
122 case 12000:
123 ret = 4;
124 break;
125 case 8000:
126 ret = 6;
127 break;
128 default:
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400129#ifdef CUSTOM_MODES
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500130 ret = 0;
Jean-Marc Valinbe89c392011-08-30 12:39:51 -0400131 break;
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400132#else
133 celt_assert(0);
134#endif
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500135 }
136 return ret;
137}
138
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400139/** Encoder state
Jean-Marc Valin276de722008-02-20 17:45:51 +1100140 @brief Encoder state
141 */
Jean-Marc Valin242da532011-09-05 20:53:33 -0400142struct OpusCustomEncoder {
143 const OpusCustomMode *mode; /**< Mode used by the encoder */
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100144 int overlap;
Jean-Marc Valinffa13472007-12-10 16:54:17 +1100145 int channels;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -0500146 int stream_channels;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400147
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400148 int force_intra;
Jean-Marc Valin0b405d12011-02-04 01:03:42 -0500149 int clip;
Jean-Marc Valind539c6b2011-02-03 13:36:03 -0500150 int disable_pf;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400151 int complexity;
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500152 int upsample;
Jean-Marc Valinc09807d2010-08-27 17:17:50 -0400153 int start, end;
154
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400155 opus_int32 bitrate;
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -0500156 int vbr;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -0500157 int signalling;
Jean-Marc Valin9faf7402010-12-04 10:27:22 -0500158 int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */
Jean-Marc Valin69653882011-04-21 10:41:13 -0400159 int loss_rate;
Jean-Marc Valinc09807d2010-08-27 17:17:50 -0400160
161 /* Everything beyond this point gets cleared on a reset */
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -0500162#define ENCODER_RESET_START rng
Jean-Marc Valinc09807d2010-08-27 17:17:50 -0400163
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400164 opus_uint32 rng;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800165 int spread_decision;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400166 opus_val32 delayedIntra;
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -0400167 int tonal_average;
Jean-Marc Valindfd6e712010-12-09 23:23:34 -0500168 int lastCodedBands;
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500169 int hf_average;
170 int tapset_decision;
Jean-Marc Valin527db5c2009-06-02 07:56:19 -0400171
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400172 int prefilter_period;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400173 opus_val16 prefilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500174 int prefilter_tapset;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -0500175#ifdef RESYNTH
176 int prefilter_period_old;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400177 opus_val16 prefilter_gain_old;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500178 int prefilter_tapset_old;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -0500179#endif
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -0500180 int consec_transient;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400181
Gregory Maxwell86dd9842011-08-12 19:03:29 -0400182 opus_val32 preemph_memE[2];
183 opus_val32 preemph_memD[2];
184
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400185 /* VBR-related parameters */
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400186 opus_int32 vbr_reservoir;
187 opus_int32 vbr_drift;
188 opus_int32 vbr_offset;
189 opus_int32 vbr_count;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -0400190
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400191#ifdef RESYNTH
192 celt_sig syn_mem[2][2*MAX_PERIOD];
193#endif
194
Jean-Marc Valinca8b9922010-08-27 16:23:03 -0400195 celt_sig in_mem[1]; /* Size = channels*mode->overlap */
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400196 /* celt_sig prefilter_mem[], Size = channels*COMBFILTER_PERIOD */
Jean-Marc Valinca8b9922010-08-27 16:23:03 -0400197 /* celt_sig overlap_mem[], Size = channels*mode->overlap */
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400198 /* opus_val16 oldEBands[], Size = 2*channels*mode->nbEBands */
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100199};
200
Jean-Marc Valin8cf29f02011-01-30 23:38:28 -0500201int celt_encoder_get_size(int channels)
202{
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400203 CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
204 return opus_custom_encoder_get_size(mode, channels);
Jean-Marc Valin8cf29f02011-01-30 23:38:28 -0500205}
206
Gregory Maxwellafc8d532011-09-28 15:13:26 -0400207OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels)
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400208{
209 int size = sizeof(struct CELTEncoder)
210 + (2*channels*mode->overlap-1)*sizeof(celt_sig)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400211 + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig)
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400212 + 3*channels*mode->nbEBands*sizeof(opus_val16);
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400213 return size;
214}
215
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400216#ifdef CUSTOM_MODES
217CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valinc97b2582011-01-28 23:07:32 -0500218{
Jean-Marc Valin875f8db2011-08-31 16:43:08 -0400219 int ret;
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400220 CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels));
Jean-Marc Valin875f8db2011-08-31 16:43:08 -0400221 /* init will handle the NULL case */
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400222 ret = opus_custom_encoder_init(st, mode, channels);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400223 if (ret != OPUS_OK)
Jean-Marc Valind6c3d3c2011-01-30 10:23:40 -0500224 {
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400225 opus_custom_encoder_destroy(st);
Jean-Marc Valind6c3d3c2011-01-30 10:23:40 -0500226 st = NULL;
227 }
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400228 if (error)
229 *error = ret;
Jean-Marc Valind6c3d3c2011-01-30 10:23:40 -0500230 return st;
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -0400231}
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400232#endif /* CUSTOM_MODES */
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100233
Gregory Maxwell64a35412011-09-02 10:31:17 -0400234int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels)
Jean-Marc Valinc97b2582011-01-28 23:07:32 -0500235{
Jean-Marc Valin875f8db2011-08-31 16:43:08 -0400236 int ret;
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400237 ret = opus_custom_encoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400238 if (ret != OPUS_OK)
Jean-Marc Valin875f8db2011-08-31 16:43:08 -0400239 return ret;
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500240 st->upsample = resampling_factor(sampling_rate);
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400241 return OPUS_OK;
Jean-Marc Valinc97b2582011-01-28 23:07:32 -0500242}
243
Gregory Maxwellafc8d532011-09-28 15:13:26 -0400244OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels)
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -0400245{
Jean-Marc Valin80ed1472009-10-15 21:45:32 -0400246 if (channels < 0 || channels > 2)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400247 return OPUS_BAD_ARG;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100248
Jean-Marc Valind6c3d3c2011-01-30 10:23:40 -0500249 if (st==NULL || mode==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400250 return OPUS_ALLOC_FAIL;
Jean-Marc Valin6d3829f2010-08-27 17:52:38 -0400251
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400252 OPUS_CLEAR((char*)st, opus_custom_encoder_get_size(mode, channels));
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400253
Jean-Marc Valin73e51b32007-12-05 17:48:24 +1100254 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100255 st->overlap = mode->overlap;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -0500256 st->stream_channels = st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +1100257
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500258 st->upsample = 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400259 st->start = 0;
Jean-Marc Valin8952c452010-07-16 21:48:44 -0400260 st->end = st->mode->effEBands;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -0500261 st->signalling = 1;
262
Jean-Marc Valin9faf7402010-12-04 10:27:22 -0500263 st->constrained_vbr = 1;
Jean-Marc Valin0b405d12011-02-04 01:03:42 -0500264 st->clip = 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -0400265
Jean-Marc Valin663a7fe2011-09-06 14:05:19 -0400266 st->bitrate = OPUS_BITRATE_MAX;
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -0500267 st->vbr = 0;
Jean-Marc Valin30165bb2010-12-03 14:35:59 -0500268 st->vbr_offset = 0;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -0400269 st->force_intra = 0;
Gregory Maxwell8842fde2009-05-04 15:58:40 -0400270 st->delayedIntra = 1;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400271 st->tonal_average = 256;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -0800272 st->spread_decision = SPREAD_NORMAL;
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500273 st->hf_average = 0;
274 st->tapset_decision = 0;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -0400275 st->complexity = 5;
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100276
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400277 return OPUS_OK;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100278}
279
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400280#ifdef CUSTOM_MODES
281void opus_custom_encoder_destroy(CELTEncoder *st)
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100282{
Jean-Marc Valin07f88402011-08-29 15:08:51 -0400283 opus_free(st);
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100284}
Jean-Marc Valin06237d72011-09-01 13:20:40 -0400285#endif /* CUSTOM_MODES */
Jean-Marc Valin14191b32007-11-30 12:15:49 +1100286
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400287static inline opus_val16 SIG2WORD16(celt_sig x)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -0400288{
289#ifdef FIXED_POINT
Jean-Marc Valin42074382008-02-27 11:08:53 +1100290 x = PSHR32(x, SIG_SHIFT);
Jean-Marc Valinabdfc382008-04-18 15:57:18 +1000291 x = MAX32(x, -32768);
292 x = MIN32(x, 32767);
Jean-Marc Valin42074382008-02-27 11:08:53 +1100293 return EXTRACT16(x);
294#else
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400295 return (opus_val16)x;
Jean-Marc Valin42074382008-02-27 11:08:53 +1100296#endif
297}
298
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400299static int transient_analysis(const opus_val32 * restrict in, int len, int C,
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -0500300 int overlap)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000301{
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500302 int i;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400303 VARDECL(opus_val16, tmp);
304 opus_val32 mem0=0,mem1=0;
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500305 int is_transient = 0;
306 int block;
307 int N;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400308 VARDECL(opus_val16, bins);
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400309 SAVE_STACK;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400310 ALLOC(tmp, len, opus_val16);
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400311
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500312 block = overlap/2;
313 N=len/block;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400314 ALLOC(bins, N, opus_val16);
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400315 if (C==1)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000316 {
317 for (i=0;i<len;i++)
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400318 tmp[i] = SHR32(in[i],SIG_SHIFT);
Jean-Marc Valin9c30de52010-04-19 13:32:15 -0400319 } else {
320 for (i=0;i<len;i++)
Jean-Marc Valin933dd832010-10-24 00:08:16 -0400321 tmp[i] = SHR32(ADD32(in[i],in[i+len]), SIG_SHIFT+1);
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000322 }
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400323
324 /* High-pass filter: (1 - 2*z^-1 + z^-2) / (1 - z^-1 + .5*z^-2) */
325 for (i=0;i<len;i++)
326 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400327 opus_val32 x,y;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400328 x = tmp[i];
329 y = ADD32(mem0, x);
330#ifdef FIXED_POINT
331 mem0 = mem1 + y - SHL32(x,1);
332 mem1 = x - SHR32(y,1);
333#else
334 mem0 = mem1 + y - 2*x;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400335 mem1 = x - .5f*y;
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400336#endif
337 tmp[i] = EXTRACT16(SHR(y,2));
338 }
339 /* First few samples are bad because we don't propagate the memory */
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500340 for (i=0;i<12;i++)
Jean-Marc Valin2794b632010-10-13 17:32:57 -0400341 tmp[i] = 0;
342
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500343 for (i=0;i<N;i++)
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000344 {
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500345 int j;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400346 opus_val16 max_abs=0;
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500347 for (j=0;j<block;j++)
Jean-Marc Valin168888f2011-03-02 17:26:48 -0500348 max_abs = MAX16(max_abs, ABS16(tmp[i*block+j]));
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500349 bins[i] = max_abs;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000350 }
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500351 for (i=0;i<N;i++)
Jean-Marc Valin4a8c1f12010-10-13 18:03:50 -0400352 {
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500353 int j;
354 int conseq=0;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400355 opus_val16 t1, t2, t3;
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500356
357 t1 = MULT16_16_Q15(QCONST16(.15f, 15), bins[i]);
358 t2 = MULT16_16_Q15(QCONST16(.4f, 15), bins[i]);
359 t3 = MULT16_16_Q15(QCONST16(.15f, 15), bins[i]);
360 for (j=0;j<i;j++)
361 {
362 if (bins[j] < t1)
363 conseq++;
364 if (bins[j] < t2)
365 conseq++;
366 else
367 conseq = 0;
368 }
369 if (conseq>=3)
370 is_transient=1;
371 conseq = 0;
372 for (j=i+1;j<N;j++)
373 {
374 if (bins[j] < t3)
375 conseq++;
376 else
377 conseq = 0;
378 }
379 if (conseq>=7)
380 is_transient=1;
Jean-Marc Valin4a8c1f12010-10-13 18:03:50 -0400381 }
Jean-Marc Valin0ceccb22008-07-03 20:41:06 -0400382 RESTORE_STACK;
Jean-Marc Valinf334c822011-08-11 16:21:58 -0400383#ifdef FUZZING
384 is_transient = rand()&0x1;
385#endif
Jean-Marc Valinfddc5212010-12-09 14:28:26 -0500386 return is_transient;
Jean-Marc Valin9375aa42008-06-27 07:57:35 +1000387}
388
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400389/** Apply window and compute the MDCT for all sub-frames and
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400390 all channels in a frame */
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400391static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig * restrict in, celt_sig * restrict out, int _C, int LM)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100392{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400393 const int C = CHANNELS(_C);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000394 if (C==1 && !shortBlocks)
Jean-Marc Valinda721882007-11-30 15:17:42 +1100395 {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000396 const int overlap = OVERLAP(mode);
Jean-Marc Valina6b4e252011-08-15 10:20:06 -0400397 clt_mdct_forward(&mode->mdct, in, out, mode->window, overlap, mode->maxLM-LM, 1);
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400398 } else {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000399 const int overlap = OVERLAP(mode);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400400 int N = mode->shortMdctSize<<LM;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400401 int B = 1;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000402 int b, c;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400403 if (shortBlocks)
404 {
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400405 N = mode->shortMdctSize;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400406 B = shortBlocks;
Jean-Marc Valinaa4f58b2009-10-03 09:27:59 -0400407 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400408 c=0; do {
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000409 for (b=0;b<B;b++)
410 {
Jean-Marc Valina6b4e252011-08-15 10:20:06 -0400411 /* Interleaving the sub-frames while doing the MDCTs */
412 clt_mdct_forward(&mode->mdct, in+c*(B*N+overlap)+b*N, &out[b+c*N*B], mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM, B);
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000413 }
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400414 } while (++c<C);
Jean-Marc Valinda721882007-11-30 15:17:42 +1100415 }
Jean-Marc Valinda721882007-11-30 15:17:42 +1100416}
417
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400418/** Compute the IMDCT and apply window for all sub-frames and
Jean-Marc Valin56522ad2009-06-05 17:17:25 -0400419 all channels in a frame */
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400420static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig *X,
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -0400421 celt_sig * restrict out_mem[],
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -0400422 celt_sig * restrict overlap_mem[], int _C, int LM)
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100423{
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -0400424 int c;
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400425 const int C = CHANNELS(_C);
Jean-Marc Valince4dd362010-05-07 07:45:18 -0400426 const int N = mode->shortMdctSize<<LM;
Jean-Marc Valinb18ec0b2008-04-11 04:07:52 +1000427 const int overlap = OVERLAP(mode);
Jean-Marc Valindbeb86f2011-08-15 10:01:00 -0400428 VARDECL(opus_val32, x);
429 SAVE_STACK;
430
431 ALLOC(x, N+overlap, opus_val32);
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400432 c=0; do {
Jean-Marc Valinb886ddc2008-03-25 14:38:55 +1100433 int j;
Jean-Marc Valindbeb86f2011-08-15 10:01:00 -0400434 int b;
435 int N2 = N;
436 int B = 1;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400437
Jean-Marc Valindbeb86f2011-08-15 10:01:00 -0400438 if (shortBlocks)
439 {
440 N2 = mode->shortMdctSize;
441 B = shortBlocks;
442 }
443 /* Prevents problems from the imdct doing the overlap-add */
Jean-Marc Valinbe89c392011-08-30 12:39:51 -0400444 OPUS_CLEAR(x, overlap);
Jean-Marc Valinde678582009-10-03 10:36:27 -0400445
Jean-Marc Valindbeb86f2011-08-15 10:01:00 -0400446 for (b=0;b<B;b++)
447 {
448 /* IMDCT on the interleaved the sub-frames */
449 clt_mdct_backward(&mode->mdct, &X[b+c*N2*B], x+N2*b, mode->window, overlap, shortBlocks ? mode->maxLM : mode->maxLM-LM, B);
450 }
Jean-Marc Valinde678582009-10-03 10:36:27 -0400451
Jean-Marc Valindbeb86f2011-08-15 10:01:00 -0400452 for (j=0;j<overlap;j++)
453 out_mem[c][j] = x[j] + overlap_mem[c][j];
454 for (;j<N;j++)
455 out_mem[c][j] = x[j];
456 for (j=0;j<overlap;j++)
457 overlap_mem[c][j] = x[N+j];
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400458 } while (++c<C);
Jean-Marc Valindbeb86f2011-08-15 10:01:00 -0400459 RESTORE_STACK;
Jean-Marc Valin1677aa92007-12-08 01:13:34 +1100460}
461
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400462static void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int _C, int downsample, const opus_val16 *coef, celt_sig *mem)
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400463{
Jean-Marc Valinbf2398b2009-10-15 07:28:19 -0400464 const int C = CHANNELS(_C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400465 int c;
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500466 int count=0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400467 c=0; do {
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400468 int j;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400469 celt_sig * restrict x;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400470 opus_val16 * restrict y;
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400471 celt_sig m = mem[c];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -0400472 x =in[c];
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400473 y = pcm+c;
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400474 for (j=0;j<N;j++)
475 {
Jean-Marc Valinaf1fce92010-07-16 11:05:06 -0400476 celt_sig tmp = *x + m;
477 m = MULT16_32_Q15(coef[0], tmp)
478 - MULT16_32_Q15(coef[1], *x);
Jean-Marc Valin223b69d2010-07-16 11:47:50 -0400479 tmp = SHL32(MULT16_32_Q15(coef[3], tmp), 2);
Jean-Marc Valin903dbf72010-08-26 20:06:49 -0400480 x++;
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500481 /* Technically the store could be moved outside of the if because
482 the stores we don't want will just be overwritten */
483 if (++count==downsample)
484 {
485 *y = SCALEOUT(SIG2WORD16(tmp));
486 y+=C;
487 count=0;
488 }
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400489 }
Jean-Marc Valin64209a32010-04-05 09:26:22 -0400490 mem[c] = m;
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400491 } while (++c<C);
Jean-Marc Valine12017e2009-10-03 13:57:31 -0400492}
493
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400494static void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
495 opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
496 const opus_val16 *window, int overlap)
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400497{
498 int i;
499 /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400500 opus_val16 g00, g01, g02, g10, g11, g12;
501 static const opus_val16 gains[3][3] = {
Jean-Marc Valin61f40412011-01-27 17:14:33 -0500502 {QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)},
503 {QCONST16(0.4638671875f, 15), QCONST16(0.2680664062f, 15), QCONST16(0.f, 15)},
504 {QCONST16(0.7998046875f, 15), QCONST16(0.1000976562f, 15), QCONST16(0.f, 15)}};
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500505 g00 = MULT16_16_Q15(g0, gains[tapset0][0]);
506 g01 = MULT16_16_Q15(g0, gains[tapset0][1]);
507 g02 = MULT16_16_Q15(g0, gains[tapset0][2]);
508 g10 = MULT16_16_Q15(g1, gains[tapset1][0]);
509 g11 = MULT16_16_Q15(g1, gains[tapset1][1]);
510 g12 = MULT16_16_Q15(g1, gains[tapset1][2]);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400511 for (i=0;i<overlap;i++)
512 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400513 opus_val16 f;
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400514 f = MULT16_16_Q15(window[i],window[i]);
515 y[i] = x[i]
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500516 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0])
517 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),x[i-T0-1])
518 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),x[i-T0+1])
519 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),x[i-T0-2])
520 + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),x[i-T0+2])
521 + MULT16_32_Q15(MULT16_16_Q15(f,g10),x[i-T1])
522 + MULT16_32_Q15(MULT16_16_Q15(f,g11),x[i-T1-1])
523 + MULT16_32_Q15(MULT16_16_Q15(f,g11),x[i-T1+1])
524 + MULT16_32_Q15(MULT16_16_Q15(f,g12),x[i-T1-2])
525 + MULT16_32_Q15(MULT16_16_Q15(f,g12),x[i-T1+2]);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400526
527 }
528 for (i=overlap;i<N;i++)
529 y[i] = x[i]
Jean-Marc Valindfa847a2011-01-17 11:37:08 -0500530 + MULT16_32_Q15(g10,x[i-T1])
531 + MULT16_32_Q15(g11,x[i-T1-1])
532 + MULT16_32_Q15(g11,x[i-T1+1])
533 + MULT16_32_Q15(g12,x[i-T1-2])
534 + MULT16_32_Q15(g12,x[i-T1+2]);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400535}
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400536
Jean-Marc Valina8160dd2010-10-12 14:55:16 -0400537static const signed char tf_select_table[4][8] = {
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400538 {0, -1, 0, -1, 0,-1, 0,-1},
Jean-Marc Valin41a15e62010-12-27 16:33:38 -0500539 {0, -1, 0, -2, 1, 0, 1,-1},
540 {0, -2, 0, -3, 2, 0, 1,-1},
Jean-Marc Valin2b134012011-01-12 16:13:46 -0500541 {0, -2, 0, -3, 3, 0, 1,-1},
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400542};
543
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400544static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, int width)
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400545{
546 int i, j;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400547 static const opus_val16 sqrtM_1[4] = {Q15ONE, QCONST16(.70710678f,15), QCONST16(0.5f,15), QCONST16(0.35355339f,15)};
548 opus_val32 L1;
549 opus_val16 bias;
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400550 L1=0;
551 for (i=0;i<1<<LM;i++)
552 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400553 opus_val32 L2 = 0;
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400554 for (j=0;j<N>>LM;j++)
555 L2 = MAC16_16(L2, tmp[(j<<LM)+i], tmp[(j<<LM)+i]);
556 L1 += celt_sqrt(L2);
557 }
558 L1 = MULT16_32_Q15(sqrtM_1[LM], L1);
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400559 if (width==1)
560 bias = QCONST16(.12f,15)*LM;
561 else if (width==2)
562 bias = QCONST16(.05f,15)*LM;
563 else
564 bias = QCONST16(.02f,15)*LM;
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400565 L1 = MAC16_32_Q15(L1, bias, L1);
566 return L1;
567}
568
Gregory Maxwell06d57b22011-08-01 22:02:25 -0400569static int tf_analysis(const CELTMode *m, int len, int C, int isTransient,
570 int *tf_res, int nbCompressedBytes, celt_norm *X, int N0, int LM,
571 int *tf_sum)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400572{
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400573 int i;
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400574 VARDECL(int, metric);
575 int cost0;
576 int cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400577 VARDECL(int, path0);
578 VARDECL(int, path1);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400579 VARDECL(celt_norm, tmp);
580 int lambda;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400581 int tf_select=0;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400582 SAVE_STACK;
583
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400584 if (nbCompressedBytes<15*C)
585 {
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400586 *tf_sum = 0;
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400587 for (i=0;i<len;i++)
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400588 tf_res[i] = isTransient;
Jean-Marc Valin6bf3b0a2010-07-19 14:32:40 -0400589 return 0;
590 }
Jean-Marc Valin73319772010-05-28 21:12:39 -0400591 if (nbCompressedBytes<40)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400592 lambda = 12;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400593 else if (nbCompressedBytes<60)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400594 lambda = 6;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400595 else if (nbCompressedBytes<100)
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400596 lambda = 4;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400597 else
Jean-Marc Valin54fb7e52010-10-15 11:26:32 -0400598 lambda = 3;
Jean-Marc Valin73319772010-05-28 21:12:39 -0400599
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400600 ALLOC(metric, len, int);
601 ALLOC(tmp, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm);
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400602 ALLOC(path0, len, int);
603 ALLOC(path1, len, int);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400604
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400605 *tf_sum = 0;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400606 for (i=0;i<len;i++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400607 {
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400608 int j, k, N;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400609 opus_val32 L1, best_L1;
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400610 int best_level=0;
611 N = (m->eBands[i+1]-m->eBands[i])<<LM;
612 for (j=0;j<N;j++)
613 tmp[j] = X[j+(m->eBands[i]<<LM)];
Jean-Marc Valin20e4c6a2010-12-21 22:27:08 -0500614 /* Just add the right channel if we're in stereo */
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400615 if (C==2)
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400616 for (j=0;j<N;j++)
Jean-Marc Valina3a066c2010-11-04 15:15:54 -0400617 tmp[j] = ADD16(tmp[j],X[N0+j+(m->eBands[i]<<LM)]);
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400618 L1 = l1_metric(tmp, N, isTransient ? LM : 0, N>>LM);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400619 best_L1 = L1;
620 /*printf ("%f ", L1);*/
621 for (k=0;k<LM;k++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400622 {
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400623 int B;
624
625 if (isTransient)
626 B = (LM-k-1);
627 else
628 B = k+1;
629
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400630 if (isTransient)
631 haar1(tmp, N>>(LM-k), 1<<(LM-k));
632 else
633 haar1(tmp, N>>k, 1<<k);
634
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400635 L1 = l1_metric(tmp, N, B, N>>LM);
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400636
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400637 if (L1 < best_L1)
638 {
639 best_L1 = L1;
640 best_level = k+1;
641 }
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400642 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400643 /*printf ("%d ", isTransient ? LM-best_level : best_level);*/
644 if (isTransient)
645 metric[i] = best_level;
646 else
647 metric[i] = -best_level;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400648 *tf_sum += metric[i];
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400649 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400650 /*printf("\n");*/
Jean-Marc Valin92675062011-09-11 22:00:46 -0400651 /* NOTE: Future optimized implementations could detect extreme transients and set
652 tf_select = 1 but so far we have not found a reliable way of making this useful */
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -0400653 tf_select = 0;
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400654
Jean-Marc Valin88232612010-05-28 18:01:02 -0400655 cost0 = 0;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400656 cost1 = isTransient ? 0 : lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400657 /* Viterbi forward pass */
658 for (i=1;i<len;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400659 {
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400660 int curr0, curr1;
661 int from0, from1;
Jean-Marc Valin581fdba2010-05-28 06:56:23 -0400662
Jean-Marc Valin88232612010-05-28 18:01:02 -0400663 from0 = cost0;
664 from1 = cost1 + lambda;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400665 if (from0 < from1)
666 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400667 curr0 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400668 path0[i]= 0;
669 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400670 curr0 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400671 path0[i]= 1;
672 }
673
Jean-Marc Valin88232612010-05-28 18:01:02 -0400674 from0 = cost0 + lambda;
675 from1 = cost1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400676 if (from0 < from1)
677 {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400678 curr1 = from0;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400679 path1[i]= 0;
680 } else {
Jean-Marc Valin88232612010-05-28 18:01:02 -0400681 curr1 = from1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400682 path1[i]= 1;
683 }
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400684 cost0 = curr0 + abs(metric[i]-tf_select_table[LM][4*isTransient+2*tf_select+0]);
685 cost1 = curr1 + abs(metric[i]-tf_select_table[LM][4*isTransient+2*tf_select+1]);
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400686 }
Jean-Marc Valin88232612010-05-28 18:01:02 -0400687 tf_res[len-1] = cost0 < cost1 ? 0 : 1;
Jean-Marc Valin9d420c52010-05-28 17:26:27 -0400688 /* Viterbi backward pass to check the decisions */
689 for (i=len-2;i>=0;i--)
690 {
691 if (tf_res[i+1] == 1)
692 tf_res[i] = path1[i+1];
693 else
694 tf_res[i] = path0[i+1];
695 }
Jean-Marc Valin71ae6d42010-06-27 21:55:08 -0400696 RESTORE_STACK;
Jean-Marc Valinf334c822011-08-11 16:21:58 -0400697#ifdef FUZZING
698 tf_select = rand()&0x1;
699 tf_res[0] = rand()&0x1;
700 for (i=1;i<len;i++)
701 tf_res[i] = tf_res[i-1] ^ ((rand()&0xF) == 0);
702#endif
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400703 return tf_select;
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400704}
705
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500706static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM, int tf_select, ec_enc *enc)
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -0400707{
708 int curr, i;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800709 int tf_select_rsv;
710 int tf_changed;
711 int logp;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400712 opus_uint32 budget;
713 opus_uint32 tell;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -0800714 budget = enc->storage*8;
715 tell = ec_tell(enc);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800716 logp = isTransient ? 2 : 4;
717 /* Reserve space to code the tf_select decision. */
718 tf_select_rsv = LM>0 && tell+logp+1 <= budget;
719 budget -= tf_select_rsv;
720 curr = tf_changed = 0;
721 for (i=start;i<end;i++)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400722 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800723 if (tell+logp<=budget)
724 {
725 ec_enc_bit_logp(enc, tf_res[i] ^ curr, logp);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -0800726 tell = ec_tell(enc);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800727 curr = tf_res[i];
728 tf_changed |= curr;
729 }
730 else
731 tf_res[i] = curr;
732 logp = isTransient ? 4 : 5;
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400733 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800734 /* Only code tf_select if it would actually make a difference. */
735 if (tf_select_rsv &&
736 tf_select_table[LM][4*isTransient+0+tf_changed]!=
737 tf_select_table[LM][4*isTransient+2+tf_changed])
738 ec_enc_bit_logp(enc, tf_select, 1);
739 else
740 tf_select = 0;
Jean-Marc Valin2ed5e672010-07-13 16:50:11 -0400741 for (i=start;i<end;i++)
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400742 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
Jean-Marc Valin0f8fc0b2010-10-12 23:25:58 -0400743 /*printf("%d %d ", isTransient, tf_select); for(i=0;i<end;i++)printf("%d ", tf_res[i]);printf("\n");*/
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400744}
745
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -0500746static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400747{
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400748 int i, curr, tf_select;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800749 int tf_select_rsv;
750 int tf_changed;
751 int logp;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400752 opus_uint32 budget;
753 opus_uint32 tell;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800754
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -0800755 budget = dec->storage*8;
756 tell = ec_tell(dec);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800757 logp = isTransient ? 2 : 4;
758 tf_select_rsv = LM>0 && tell+logp+1<=budget;
759 budget -= tf_select_rsv;
760 tf_changed = curr = 0;
761 for (i=start;i<end;i++)
Timothy B. Terriberry509ad202010-12-27 18:20:20 -0800762 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800763 if (tell+logp<=budget)
764 {
765 curr ^= ec_dec_bit_logp(dec, logp);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -0800766 tell = ec_tell(dec);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800767 tf_changed |= curr;
768 }
769 tf_res[i] = curr;
770 logp = isTransient ? 4 : 5;
771 }
772 tf_select = 0;
773 if (tf_select_rsv &&
774 tf_select_table[LM][4*isTransient+0+tf_changed] !=
775 tf_select_table[LM][4*isTransient+2+tf_changed])
776 {
777 tf_select = ec_dec_bit_logp(dec, 1);
778 }
779 for (i=start;i<end;i++)
780 {
781 tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
Timothy B. Terriberry509ad202010-12-27 18:20:20 -0800782 }
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400783}
784
Timothy B. Terriberryce6d0902011-02-01 17:41:12 -0800785static void init_caps(const CELTMode *m,int *cap,int LM,int C)
786{
787 int i;
788 for (i=0;i<m->nbEBands;i++)
789 {
790 int N;
791 N=(m->eBands[i+1]-m->eBands[i])<<LM;
792 cap[i] = (m->cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2;
793 }
794}
795
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400796static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400797 const opus_val16 *bandLogE, int end, int LM, int C, int N0)
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400798{
799 int i;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400800 opus_val32 diff=0;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500801 int c;
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500802 int trim_index = 5;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400803 if (C==2)
804 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400805 opus_val16 sum = 0; /* Q10 */
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400806 /* Compute inter-channel correlation for low frequencies */
807 for (i=0;i<8;i++)
808 {
809 int j;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400810 opus_val32 partial = 0;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400811 for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
812 partial = MAC16_16(partial, X[j], X[N0+j]);
813 sum = ADD16(sum, EXTRACT16(SHR32(partial, 18)));
814 }
815 sum = MULT16_16_Q15(QCONST16(1.f/8, 15), sum);
816 /*printf ("%f\n", sum);*/
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400817 if (sum > QCONST16(.995f,10))
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500818 trim_index-=4;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400819 else if (sum > QCONST16(.92f,10))
Jean-Marc Valin4b087df2010-11-30 21:08:31 -0500820 trim_index-=3;
821 else if (sum > QCONST16(.85f,10))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400822 trim_index-=2;
Gregory Maxwell60c316b2010-11-04 20:14:19 -0400823 else if (sum > QCONST16(.8f,10))
Jean-Marc Valinc40addc2010-10-22 14:57:07 -0400824 trim_index-=1;
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400825 }
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500826
827 /* Estimate spectral tilt */
Gregory Maxwell9743bf32010-11-04 20:45:09 -0400828 c=0; do {
Gregory Maxwell7007f1b2011-02-08 16:17:47 -0500829 for (i=0;i<end-1;i++)
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400830 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400831 diff += bandLogE[i+c*m->nbEBands]*(opus_int32)(2+2*i-m->nbEBands);
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400832 }
Gregory Maxwellf93d81b2011-08-07 00:57:31 -0400833 } while (++c<C);
Jean-Marc Valin817220e2011-08-08 11:33:17 -0400834 /* We divide by two here to avoid making the tilt larger for stereo as a
835 result of a bug in the loop above */
836 diff /= 2*C*(end-1);
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400837 /*printf("%f\n", diff);*/
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500838 if (diff > QCONST16(2.f, DB_SHIFT))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400839 trim_index--;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500840 if (diff > QCONST16(8.f, DB_SHIFT))
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400841 trim_index--;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500842 if (diff < -QCONST16(4.f, DB_SHIFT))
Jean-Marc Valin90377572010-10-22 15:12:01 -0400843 trim_index++;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500844 if (diff < -QCONST16(10.f, DB_SHIFT))
845 trim_index++;
846
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400847 if (trim_index<0)
848 trim_index = 0;
Jean-Marc Valin546dfa12010-12-10 17:18:17 -0500849 if (trim_index>10)
850 trim_index = 10;
Jean-Marc Valinf334c822011-08-11 16:21:58 -0400851#ifdef FUZZING
852 trim_index = rand()%11;
853#endif
Jean-Marc Valinc5792de2010-10-19 14:24:50 -0400854 return trim_index;
855}
856
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500857static int stereo_analysis(const CELTMode *m, const celt_norm *X,
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -0500858 int LM, int N0)
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500859{
860 int i;
861 int thetas;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400862 opus_val32 sumLR = EPSILON, sumMS = EPSILON;
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500863
864 /* Use the L1 norm to model the entropy of the L/R signal vs the M/S signal */
865 for (i=0;i<13;i++)
866 {
867 int j;
868 for (j=m->eBands[i]<<LM;j<m->eBands[i+1]<<LM;j++)
869 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400870 opus_val16 L, R, M, S;
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500871 L = X[j];
872 R = X[N0+j];
873 M = L+R;
874 S = L-R;
875 sumLR += EXTEND32(ABS16(L)) + EXTEND32(ABS16(R));
876 sumMS += EXTEND32(ABS16(M)) + EXTEND32(ABS16(S));
877 }
878 }
879 sumMS = MULT16_32_Q15(QCONST16(0.707107f, 15), sumMS);
880 thetas = 13;
881 /* We don't need thetas for lower bands with LM<=1 */
882 if (LM<=1)
883 thetas -= 8;
884 return MULT16_32_Q15((m->eBands[13]<<(LM+1))+thetas, sumMS)
885 > MULT16_32_Q15(m->eBands[13]<<(LM+1), sumLR);
886}
887
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400888int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc)
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +1100889{
Jean-Marc Valin7a08ddd2010-10-18 14:55:42 -0400890 int i, c, N;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400891 opus_int32 bits;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -0800892 ec_enc _enc;
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400893 VARDECL(celt_sig, in);
894 VARDECL(celt_sig, freq);
Jean-Marc Valin234969c2009-10-17 22:12:42 -0400895 VARDECL(celt_norm, X);
896 VARDECL(celt_ener, bandE);
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400897 VARDECL(opus_val16, bandLogE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400898 VARDECL(int, fine_quant);
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400899 VARDECL(opus_val16, error);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400900 VARDECL(int, pulses);
Timothy B. Terriberryc5643072011-01-29 12:57:18 -0800901 VARDECL(int, cap);
Jean-Marc Valin6775de32008-08-02 08:14:42 -0400902 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -0400903 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -0400904 VARDECL(int, tf_res);
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -0800905 VARDECL(unsigned char, collapse_masks);
Jean-Marc Valin35095c62010-11-04 13:24:44 -0400906 celt_sig *prefilter_mem;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400907 opus_val16 *oldBandE, *oldLogE, *oldLogE2;
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +1000908 int shortBlocks=0;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -0400909 int isTransient=0;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -0500910 const int CC = CHANNELS(st->channels);
911 const int C = CHANNELS(st->stream_channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400912 int LM, M;
Jean-Marc Valin890a9c02010-06-13 08:06:28 -0400913 int tf_select;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400914 int nbFilledBytes, nbAvailableBytes;
Jean-Marc Valin85f41b22010-07-16 18:12:45 -0400915 int effEnd;
Jean-Marc Valinb801da52010-09-28 14:56:20 -0400916 int codedBands;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -0400917 int tf_sum;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -0400918 int alloc_trim;
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -0500919 int pitch_index=COMBFILTER_MINPERIOD;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400920 opus_val16 gain1 = 0;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -0500921 int intensity=0;
Jean-Marc Valine65978f2010-12-02 13:46:48 -0500922 int dual_stereo=0;
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -0500923 int effectiveBytes;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400924 opus_val16 pf_threshold;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800925 int dynalloc_logp;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400926 opus_int32 vbr_rate;
927 opus_int32 total_bits;
928 opus_int32 total_boost;
929 opus_int32 balance;
930 opus_int32 tell;
Jean-Marc Valin8d367022011-01-17 16:37:51 -0500931 int prefilter_tapset=0;
932 int pf_on;
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -0800933 int anti_collapse_rsv;
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -0500934 int anti_collapse_on=0;
Jean-Marc Valinde79c372011-01-26 09:24:33 -0500935 int silence=0;
Jean-Marc Valinf62b3bb2011-03-09 11:56:29 -0500936 ALLOC_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +1100937
Jean-Marc Valinb3dae4b2011-02-04 21:50:54 -0500938 if (nbCompressedBytes<2 || pcm==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400939 return OPUS_BAD_ARG;
Gregory Maxwell520eeae2009-02-09 01:33:21 -0500940
Jean-Marc Valin913a1742011-01-29 10:00:20 -0500941 frame_size *= st->upsample;
Gregory Maxwell95becbe2011-02-03 21:06:43 -0500942 for (LM=0;LM<=st->mode->maxLM;LM++)
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400943 if (st->mode->shortMdctSize<<LM==frame_size)
944 break;
Gregory Maxwell95becbe2011-02-03 21:06:43 -0500945 if (LM>st->mode->maxLM)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400946 return OPUS_BAD_ARG;
Jean-Marc Valin017fa852010-05-06 22:11:48 -0400947 M=1<<LM;
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -0500948 N = M*st->mode->shortMdctSize;
Jean-Marc Valin8679a802008-10-18 07:44:35 -0400949
Jean-Marc Valin00a98f52011-01-31 11:19:03 -0500950 prefilter_mem = st->in_mem+CC*(st->overlap);
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400951 oldBandE = (opus_val16*)(st->in_mem+CC*(2*st->overlap+COMBFILTER_MAXPERIOD));
Jean-Marc Valin00a98f52011-01-31 11:19:03 -0500952 oldLogE = oldBandE + CC*st->mode->nbEBands;
953 oldLogE2 = oldLogE + CC*st->mode->nbEBands;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -0400954
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400955 if (enc==NULL)
956 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800957 tell=1;
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400958 nbFilledBytes=0;
959 } else {
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -0800960 tell=ec_tell(enc);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -0800961 nbFilledBytes=(tell+4)>>3;
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -0400962 }
Jean-Marc Valine6acfe02011-03-11 16:31:24 -0500963
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400964#ifdef CUSTOM_MODES
Jean-Marc Valine6acfe02011-03-11 16:31:24 -0500965 if (st->signalling && enc==NULL)
966 {
967 int tmp = (st->mode->effEBands-st->end)>>1;
968 st->end = IMAX(1, st->mode->effEBands-tmp);
969 compressed[0] = tmp<<5;
970 compressed[0] |= LM<<3;
971 compressed[0] |= (C==2)<<2;
Jean-Marc Valind6bf19d2011-03-21 07:06:09 -0400972 /* Convert "standard mode" to Opus header */
973 if (st->mode->Fs==48000 && st->mode->shortMdctSize==120)
974 {
975 int c0 = toOpus(compressed[0]);
976 if (c0<0)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400977 return OPUS_BAD_ARG;
Jean-Marc Valind6bf19d2011-03-21 07:06:09 -0400978 compressed[0] = c0;
979 }
Jean-Marc Valine6acfe02011-03-11 16:31:24 -0500980 compressed++;
981 nbCompressedBytes--;
982 }
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400983#else
984 celt_assert(st->signalling==0);
985#endif
Jean-Marc Valine6acfe02011-03-11 16:31:24 -0500986
987 /* Can't produce more than 1275 output bytes */
988 nbCompressedBytes = IMIN(nbCompressedBytes,1275);
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -0400989 nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
990
Jean-Marc Valin663a7fe2011-09-06 14:05:19 -0400991 if (st->vbr && st->bitrate!=OPUS_BITRATE_MAX)
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -0500992 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -0400993 opus_int32 den=st->mode->Fs>>BITRES;
Jean-Marc Valin23340e22011-02-03 23:21:00 -0500994 vbr_rate=(st->bitrate*frame_size+(den>>1))/den;
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400995#ifdef CUSTOM_MODES
Jean-Marc Valine6acfe02011-03-11 16:31:24 -0500996 if (st->signalling)
997 vbr_rate -= 8<<BITRES;
Gregory Maxwellfd17eab2011-10-04 03:31:45 -0400998#endif
Jean-Marc Valin3beb70e2011-03-01 18:08:15 -0500999 effectiveBytes = vbr_rate>>(3+BITRES);
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001000 } else {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001001 opus_int32 tmp;
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001002 vbr_rate = 0;
1003 tmp = st->bitrate*frame_size;
1004 if (tell>1)
1005 tmp += tell;
Jean-Marc Valin663a7fe2011-09-06 14:05:19 -04001006 if (st->bitrate!=OPUS_BITRATE_MAX)
Jean-Marc Valin66ff26f2011-08-15 22:37:11 -04001007 nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes,
1008 (tmp+4*st->mode->Fs)/(8*st->mode->Fs)-!!st->signalling));
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001009 effectiveBytes = nbCompressedBytes;
1010 }
1011
1012 if (enc==NULL)
1013 {
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001014 ec_enc_init(&_enc, compressed, nbCompressedBytes);
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001015 enc = &_enc;
1016 }
1017
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001018 if (vbr_rate>0)
1019 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001020 /* Computes the max bit-rate allowed in VBR mode to avoid violating the
1021 target rate and buffering.
1022 We must do this up front so that bust-prevention logic triggers
1023 correctly if we don't have enough bits. */
1024 if (st->constrained_vbr)
1025 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001026 opus_int32 vbr_bound;
1027 opus_int32 max_allowed;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001028 /* We could use any multiple of vbr_rate as bound (depending on the
1029 delay).
Gregory Maxwell420c3252011-01-27 22:35:50 -05001030 This is clamped to ensure we use at least two bytes if the encoder
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001031 was entirely empty, but to allow 0 in hybrid mode. */
1032 vbr_bound = vbr_rate;
Gregory Maxwell420c3252011-01-27 22:35:50 -05001033 max_allowed = IMIN(IMAX(tell==1?2:0,
Gregory Maxwell75d27802011-08-30 14:02:41 -04001034 (vbr_rate+vbr_bound-st->vbr_reservoir)>>(BITRES+3)),
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001035 nbAvailableBytes);
1036 if(max_allowed < nbAvailableBytes)
1037 {
1038 nbCompressedBytes = nbFilledBytes+max_allowed;
1039 nbAvailableBytes = max_allowed;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001040 ec_enc_shrink(enc, nbCompressedBytes);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001041 }
1042 }
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001043 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001044 total_bits = nbCompressedBytes*8;
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001045
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001046 effEnd = st->end;
1047 if (effEnd > st->mode->effEBands)
1048 effEnd = st->mode->effEBands;
1049
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001050 ALLOC(in, CC*(N+st->overlap), celt_sig);
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001051
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001052 /* Find pitch period and gain */
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +11001053 {
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001054 VARDECL(celt_sig, _pre);
1055 celt_sig *pre[2];
1056 SAVE_STACK;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001057 ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001058
1059 pre[0] = _pre;
1060 pre[1] = _pre + (N+COMBFILTER_MAXPERIOD);
1061
Jean-Marc Valinde79c372011-01-26 09:24:33 -05001062 silence = 1;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001063 c=0; do {
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001064 int count = 0;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001065 const opus_val16 * restrict pcmp = pcm+c;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001066 celt_sig * restrict inp = in+c*(N+st->overlap)+st->overlap;
1067
1068 for (i=0;i<N;i++)
1069 {
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001070 celt_sig x, tmp;
1071
1072 x = SCALEIN(*pcmp);
Jean-Marc Valin0b405d12011-02-04 01:03:42 -05001073#ifndef FIXED_POINT
Gregory Maxwell58ecb1a2011-05-09 13:16:30 -04001074 if (!(x==x))
1075 x = 0;
Jean-Marc Valin0b405d12011-02-04 01:03:42 -05001076 if (st->clip)
1077 x = MAX32(-65536.f, MIN32(65536.f,x));
1078#endif
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001079 if (++count==st->upsample)
1080 {
1081 count=0;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001082 pcmp+=CC;
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001083 } else {
1084 x = 0;
1085 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001086 /* Apply pre-emphasis */
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001087 tmp = MULT16_16(st->mode->preemph[2], x);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001088 *inp = tmp + st->preemph_memE[c];
1089 st->preemph_memE[c] = MULT16_32_Q15(st->mode->preemph[1], *inp)
1090 - MULT16_32_Q15(st->mode->preemph[0], tmp);
Jean-Marc Valinde79c372011-01-26 09:24:33 -05001091 silence = silence && *inp == 0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001092 inp++;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001093 }
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001094 OPUS_COPY(pre[c], prefilter_mem+c*COMBFILTER_MAXPERIOD, COMBFILTER_MAXPERIOD);
1095 OPUS_COPY(pre[c]+COMBFILTER_MAXPERIOD, in+c*(N+st->overlap)+st->overlap, N);
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001096 } while (++c<CC);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001097
Jean-Marc Valinf334c822011-08-11 16:21:58 -04001098#ifdef FUZZING
1099 if ((rand()&0x3F)==0)
1100 silence = 1;
1101#endif
Jean-Marc Valin65d35a32011-01-26 22:04:59 -05001102 if (tell==1)
1103 ec_enc_bit_logp(enc, silence, 15);
1104 else
1105 silence=0;
Jean-Marc Valinde79c372011-01-26 09:24:33 -05001106 if (silence)
1107 {
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001108 /*In VBR mode there is no need to send more than the minimum. */
1109 if (vbr_rate>0)
1110 {
Jean-Marc Valin65d35a32011-01-26 22:04:59 -05001111 effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2);
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001112 total_bits=nbCompressedBytes*8;
1113 nbAvailableBytes=2;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001114 ec_enc_shrink(enc, nbCompressedBytes);
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001115 }
Jean-Marc Valin13a7c262011-01-26 10:58:33 -05001116 /* Pretend we've filled all the remaining bits with zeros
1117 (that's what the initialiser did anyway) */
Jean-Marc Valinde79c372011-01-26 09:24:33 -05001118 tell = nbCompressedBytes*8;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001119 enc->nbits_total+=tell-ec_tell(enc);
Jean-Marc Valinde79c372011-01-26 09:24:33 -05001120 }
Jean-Marc Valind539c6b2011-02-03 13:36:03 -05001121 if (nbAvailableBytes>12*C && st->start==0 && !silence && !st->disable_pf && st->complexity >= 5)
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001122 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001123 VARDECL(opus_val16, pitch_buf);
1124 ALLOC(pitch_buf, (COMBFILTER_MAXPERIOD+N)>>1, opus_val16);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001125
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001126 pitch_downsample(pre, pitch_buf, COMBFILTER_MAXPERIOD+N, CC);
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -05001127 pitch_search(pitch_buf+(COMBFILTER_MAXPERIOD>>1), pitch_buf, N,
Jean-Marc Valine3e2c262011-01-26 13:09:53 -05001128 COMBFILTER_MAXPERIOD-COMBFILTER_MINPERIOD, &pitch_index);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001129 pitch_index = COMBFILTER_MAXPERIOD-pitch_index;
1130
1131 gain1 = remove_doubling(pitch_buf, COMBFILTER_MAXPERIOD, COMBFILTER_MINPERIOD,
1132 N, &pitch_index, st->prefilter_period, st->prefilter_gain);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001133 if (pitch_index > COMBFILTER_MAXPERIOD-2)
1134 pitch_index = COMBFILTER_MAXPERIOD-2;
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -05001135 gain1 = MULT16_16_Q15(QCONST16(.7f,15),gain1);
Jean-Marc Valin69653882011-04-21 10:41:13 -04001136 if (st->loss_rate>2)
1137 gain1 = HALF32(gain1);
1138 if (st->loss_rate>4)
1139 gain1 = HALF32(gain1);
1140 if (st->loss_rate>8)
1141 gain1 = 0;
Jean-Marc Valin8d367022011-01-17 16:37:51 -05001142 prefilter_tapset = st->tapset_decision;
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -05001143 } else {
1144 gain1 = 0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001145 }
Jean-Marc Valin6ba0b352010-12-20 11:40:30 -05001146
1147 /* Gain threshold for enabling the prefilter/postfilter */
1148 pf_threshold = QCONST16(.2f,15);
1149
1150 /* Adjusting the threshold based on rate and continuity */
1151 if (abs(pitch_index-st->prefilter_period)*10>pitch_index)
1152 pf_threshold += QCONST16(.2f,15);
1153 if (nbAvailableBytes<25)
1154 pf_threshold += QCONST16(.1f,15);
1155 if (nbAvailableBytes<35)
1156 pf_threshold += QCONST16(.1f,15);
1157 if (st->prefilter_gain > QCONST16(.4f,15))
1158 pf_threshold -= QCONST16(.1f,15);
1159 if (st->prefilter_gain > QCONST16(.55f,15))
1160 pf_threshold -= QCONST16(.1f,15);
1161
1162 /* Hard threshold at 0.2 */
1163 pf_threshold = MAX16(pf_threshold, QCONST16(.2f,15));
1164 if (gain1<pf_threshold)
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001165 {
Jean-Marc Valinef986e42011-02-03 15:47:10 -05001166 if(st->start==0 && tell+16<=total_bits)
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001167 ec_enc_bit_logp(enc, 0, 1);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001168 gain1 = 0;
Jean-Marc Valin8d367022011-01-17 16:37:51 -05001169 pf_on = 0;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001170 } else {
Jean-Marc Valinef986e42011-02-03 15:47:10 -05001171 /*This block is not gated by a total bits check only because
1172 of the nbAvailableBytes check above.*/
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001173 int qg;
1174 int octave;
Jean-Marc Valin6ba0b352010-12-20 11:40:30 -05001175
Jean-Marc Valinb417d832011-01-27 17:19:49 -05001176 if (ABS16(gain1-st->prefilter_gain)<QCONST16(.1f,15))
Jean-Marc Valin6ba0b352010-12-20 11:40:30 -05001177 gain1=st->prefilter_gain;
1178
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001179#ifdef FIXED_POINT
Jean-Marc Valinef986e42011-02-03 15:47:10 -05001180 qg = ((gain1+1536)>>10)/3-1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001181#else
Gregory Maxwell662587d2011-08-01 20:41:54 -04001182 qg = (int)floor(.5f+gain1*32/3)-1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001183#endif
Jean-Marc Valinef986e42011-02-03 15:47:10 -05001184 qg = IMAX(0, IMIN(7, qg));
Timothy B. Terriberrye86fb262010-12-17 14:50:19 -08001185 ec_enc_bit_logp(enc, 1, 1);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001186 pitch_index += 1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001187 octave = EC_ILOG(pitch_index)-5;
1188 ec_enc_uint(enc, octave, 6);
1189 ec_enc_bits(enc, pitch_index-(16<<octave), 4+octave);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001190 pitch_index -= 1;
Jean-Marc Valinef986e42011-02-03 15:47:10 -05001191 ec_enc_bits(enc, qg, 3);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001192 if (ec_tell(enc)+2<=total_bits)
Jean-Marc Valinef986e42011-02-03 15:47:10 -05001193 ec_enc_icdf(enc, prefilter_tapset, tapset_icdf, 2);
1194 else
1195 prefilter_tapset = 0;
1196 gain1 = QCONST16(0.09375f,15)*(qg+1);
Jean-Marc Valin8d367022011-01-17 16:37:51 -05001197 pf_on = 1;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001198 }
1199 /*printf("%d %f\n", pitch_index, gain1);*/
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001200
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001201 c=0; do {
Jean-Marc Valin64805fd2011-02-12 00:50:53 -05001202 int offset = st->mode->shortMdctSize-st->mode->overlap;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001203 st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001204 OPUS_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap);
Jean-Marc Valin64805fd2011-02-12 00:50:53 -05001205 if (offset)
1206 comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD,
1207 st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain,
1208 st->prefilter_tapset, st->prefilter_tapset, NULL, 0);
1209
1210 comb_filter(in+c*(N+st->overlap)+st->overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset,
1211 st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001212 st->prefilter_tapset, prefilter_tapset, st->mode->window, st->mode->overlap);
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001213 OPUS_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001214
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001215 if (N>COMBFILTER_MAXPERIOD)
1216 {
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001217 OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, pre[c]+N, COMBFILTER_MAXPERIOD);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001218 } else {
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001219 OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD, prefilter_mem+c*COMBFILTER_MAXPERIOD+N, COMBFILTER_MAXPERIOD-N);
1220 OPUS_MOVE(prefilter_mem+c*COMBFILTER_MAXPERIOD+COMBFILTER_MAXPERIOD-N, pre[c]+COMBFILTER_MAXPERIOD, N);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001221 }
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001222 } while (++c<CC);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001223
1224 RESTORE_STACK;
Jean-Marc Valin6f7e83d2007-12-01 00:36:41 +11001225 }
Jean-Marc Valin2014ca32009-06-18 23:33:04 -04001226
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001227 isTransient = 0;
1228 shortBlocks = 0;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001229 if (LM>0 && ec_tell(enc)+3<=total_bits)
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001230 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001231 if (st->complexity > 1)
1232 {
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001233 isTransient = transient_analysis(in, N+st->overlap, CC,
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -05001234 st->overlap);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001235 if (isTransient)
1236 shortBlocks = M;
1237 }
1238 ec_enc_bit_logp(enc, isTransient, 3);
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001239 }
Jean-Marc Valinc5f2a9d2008-10-26 22:00:26 -04001240
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001241 ALLOC(freq, CC*N, celt_sig); /**< Interleaved signal MDCTs */
1242 ALLOC(bandE,st->mode->nbEBands*CC, celt_ener);
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001243 ALLOC(bandLogE,st->mode->nbEBands*CC, opus_val16);
Jean-Marc Valin32ec58c2009-05-01 21:28:58 -04001244 /* Compute MDCTs */
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001245 compute_mdcts(st->mode, shortBlocks, in, freq, CC, LM);
Jean-Marc Valin08a82ff2009-06-14 14:05:19 -04001246
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001247 if (CC==2&&C==1)
1248 {
1249 for (i=0;i<N;i++)
1250 freq[i] = ADD32(HALF32(freq[i]), HALF32(freq[N+i]));
1251 }
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001252 if (st->upsample != 1)
1253 {
1254 c=0; do
1255 {
1256 int bound = N/st->upsample;
1257 for (i=0;i<bound;i++)
1258 freq[c*N+i] *= st->upsample;
1259 for (;i<N;i++)
1260 freq[c*N+i] = 0;
1261 } while (++c<C);
1262 }
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001263 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
Jean-Marc Valin8d4ac152008-02-29 17:24:02 +11001264
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001265 compute_band_energies(st->mode, freq, bandE, effEnd, C, M);
Jean-Marc Valin504fb3c2010-08-06 15:56:22 -04001266
1267 amp2Log2(st->mode, effEnd, st->end, bandE, bandLogE, C);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001268
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001269 /* Band normalisation */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001270 normalise_bands(st->mode, freq, X, bandE, effEnd, C, M);
Jean-Marc Valin4c77ea92009-09-14 22:50:41 -04001271
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -04001272 ALLOC(tf_res, st->mode->nbEBands, int);
Gregory Maxwell06d57b22011-08-01 22:02:25 -04001273 tf_select = tf_analysis(st->mode, effEnd, C, isTransient, tf_res, effectiveBytes, X, N, LM, &tf_sum);
Jean-Marc Valin8200b2d2010-10-15 02:18:47 -04001274 for (i=effEnd;i<st->end;i++)
1275 tf_res[i] = tf_res[effEnd-1];
1276
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001277 ALLOC(error, C*st->mode->nbEBands, opus_val16);
Jean-Marc Valin5e7f02d2010-08-08 09:48:22 -04001278 quant_coarse_energy(st->mode, st->start, st->end, effEnd, bandLogE,
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001279 oldBandE, total_bits, error, enc,
Timothy B. Terriberryef2e6502010-11-09 01:43:18 -08001280 C, LM, nbAvailableBytes, st->force_intra,
Jean-Marc Valineda2dee2011-04-21 16:04:27 -04001281 &st->delayedIntra, st->complexity >= 4, st->loss_rate);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001282
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001283 tf_encode(st->start, st->end, isTransient, tf_res, LM, tf_select, enc);
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001284
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001285 st->spread_decision = SPREAD_NORMAL;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001286 if (ec_tell(enc)+4<=total_bits)
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -04001287 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001288 if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C)
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001289 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001290 if (st->complexity == 0)
1291 st->spread_decision = SPREAD_NONE;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001292 } else {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001293 st->spread_decision = spreading_decision(st->mode, X,
Jean-Marc Valin8d367022011-01-17 16:37:51 -05001294 &st->tonal_average, st->spread_decision, &st->hf_average,
1295 &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M);
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001296 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001297 ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5);
Jean-Marc Valin1d17b9a2010-08-31 14:51:58 -04001298 }
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04001299
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08001300 ALLOC(cap, st->mode->nbEBands, int);
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001301 ALLOC(offsets, st->mode->nbEBands, int);
1302
Timothy B. Terriberryce6d0902011-02-01 17:41:12 -08001303 init_caps(st->mode,cap,LM,C);
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08001304 for (i=0;i<st->mode->nbEBands;i++)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001305 offsets[i] = 0;
1306 /* Dynamic allocation code */
1307 /* Make sure that dynamic allocation can't make us bust the budget */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001308 if (effectiveBytes > 50 && LM>=1)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001309 {
1310 int t1, t2;
1311 if (LM <= 1)
1312 {
1313 t1 = 3;
1314 t2 = 5;
1315 } else {
1316 t1 = 2;
1317 t2 = 4;
1318 }
Gregory Maxwell7007f1b2011-02-08 16:17:47 -05001319 for (i=st->start+1;i<st->end-1;i++)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001320 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001321 opus_val32 d2;
Jean-Marc Valina3a066c2010-11-04 15:15:54 -04001322 d2 = 2*bandLogE[i]-bandLogE[i-1]-bandLogE[i+1];
1323 if (C==2)
1324 d2 = HALF32(d2 + 2*bandLogE[i+st->mode->nbEBands]-
1325 bandLogE[i-1+st->mode->nbEBands]-bandLogE[i+1+st->mode->nbEBands]);
Jean-Marc Valinf334c822011-08-11 16:21:58 -04001326#ifdef FUZZING
1327 if((rand()&0xF)==0)
1328 {
1329 offsets[i] += 1;
1330 if((rand()&0x3)==0)
1331 offsets[i] += 1+(rand()&0x3);
1332 }
1333#else
Jean-Marc Valina3a066c2010-11-04 15:15:54 -04001334 if (d2 > SHL16(t1,DB_SHIFT))
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001335 offsets[i] += 1;
Jean-Marc Valina3a066c2010-11-04 15:15:54 -04001336 if (d2 > SHL16(t2,DB_SHIFT))
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001337 offsets[i] += 1;
Jean-Marc Valinf334c822011-08-11 16:21:58 -04001338#endif
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001339 }
1340 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001341 dynalloc_logp = 6;
1342 total_bits<<=BITRES;
1343 total_boost = 0;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001344 tell = ec_tell_frac(enc);
Timothy B. Terriberryd6f61572010-12-30 09:04:16 -08001345 for (i=st->start;i<st->end;i++)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001346 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001347 int width, quanta;
1348 int dynalloc_loop_logp;
1349 int boost;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001350 int j;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001351 width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])<<LM;
1352 /* quanta is 6 bits, but no more than 1 bit/sample
1353 and no less than 1/8 bit/sample */
1354 quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
1355 dynalloc_loop_logp = dynalloc_logp;
1356 boost = 0;
1357 for (j = 0; tell+(dynalloc_loop_logp<<BITRES) < total_bits-total_boost
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08001358 && boost < cap[i]; j++)
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001359 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001360 int flag;
1361 flag = j<offsets[i];
1362 ec_enc_bit_logp(enc, flag, dynalloc_loop_logp);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001363 tell = ec_tell_frac(enc);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001364 if (!flag)
1365 break;
1366 boost += quanta;
1367 total_boost += quanta;
1368 dynalloc_loop_logp = 1;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001369 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001370 /* Making dynalloc more likely */
1371 if (j)
1372 dynalloc_logp = IMAX(2, dynalloc_logp-1);
1373 offsets[i] = boost;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001374 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001375 alloc_trim = 5;
1376 if (tell+(6<<BITRES) <= total_bits - total_boost)
1377 {
1378 alloc_trim = alloc_trim_analysis(st->mode, X, bandLogE,
Gregory Maxwell7007f1b2011-02-08 16:17:47 -05001379 st->end, LM, C, N);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001380 ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001381 tell = ec_tell_frac(enc);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001382 }
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04001383
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001384 /* Variable bitrate */
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001385 if (vbr_rate>0)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001386 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001387 opus_val16 alpha;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001388 opus_int32 delta;
Gregory Maxwella9411472010-10-28 03:52:21 -04001389 /* The target rate in 8th bits per frame */
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001390 opus_int32 target;
1391 opus_int32 min_allowed;
Gregory Maxwellde0b9772011-08-23 02:00:55 -04001392 int lm_diff = st->mode->maxLM - LM;
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001393
Gregory Maxwellde0b9772011-08-23 02:00:55 -04001394 target = vbr_rate + (st->vbr_offset>>lm_diff) - ((40*C+20)<<BITRES);
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001395
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001396 /* Shortblocks get a large boost in bitrate, but since they
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001397 are uncommon long blocks are not greatly affected */
1398 if (shortBlocks || tf_sum < -2*(st->end-st->start))
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001399 target = 7*target/4;
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001400 else if (tf_sum < -(st->end-st->start))
1401 target = 3*target/2;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04001402 else if (M > 1)
Jean-Marc Valinccd5a612010-10-13 01:11:55 -04001403 target-=(target+14)/28;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001404
Gregory Maxwella9411472010-10-28 03:52:21 -04001405 /* The current offset is removed from the target and the space used
1406 so far is added*/
Jean-Marc Valina4badac2010-12-03 15:20:11 -05001407 target=target+tell;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001408
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001409 /* In VBR mode the frame size must not be reduced so much that it would
1410 result in the encoder running out of bits.
1411 The margin of 2 bytes ensures that none of the bust-prevention logic
1412 in the decoder will have triggered so far. */
Gregory Maxwell75d27802011-08-30 14:02:41 -04001413 min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes;
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001414
Gregory Maxwell75d27802011-08-30 14:02:41 -04001415 nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3);
Gregory Maxwelld85018c2011-01-13 14:38:24 -05001416 nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes);
1417 nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes;
Jean-Marc Valin6b565262011-01-12 11:27:03 -05001418
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001419 /* By how much did we "miss" the target on that frame */
1420 delta = target - vbr_rate;
1421
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001422 target=nbAvailableBytes<<(BITRES+3);
1423
Gregory Maxwellfdd86752011-04-13 17:08:22 -04001424 /*If the frame is silent we don't adjust our drift, otherwise
1425 the encoder will shoot to very high rates after hitting a
1426 span of silence, but we do allow the bitres to refill.
1427 This means that we'll undershoot our target in CVBR/VBR modes
1428 on files with lots of silence. */
1429 if(silence)
1430 {
1431 nbAvailableBytes = 2;
1432 target = 2*8<<BITRES;
1433 delta = 0;
1434 }
1435
Gregory Maxwella9411472010-10-28 03:52:21 -04001436 if (st->vbr_count < 970)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001437 {
1438 st->vbr_count++;
Gregory Maxwella9411472010-10-28 03:52:21 -04001439 alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+20),16));
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001440 } else
1441 alpha = QCONST16(.001f,15);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001442 /* How many bits have we used in excess of what we're allowed */
Jean-Marc Valin9faf7402010-12-04 10:27:22 -05001443 if (st->constrained_vbr)
1444 st->vbr_reservoir += target - vbr_rate;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001445 /*printf ("%d\n", st->vbr_reservoir);*/
1446
1447 /* Compute the offset we need to apply in order to reach the target */
Jean-Marc Valin803ec8c2011-09-23 23:48:40 -04001448 st->vbr_drift += (opus_int32)MULT16_32_Q15(alpha,(delta*(1<<lm_diff))-st->vbr_offset-st->vbr_drift);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001449 st->vbr_offset = -st->vbr_drift;
1450 /*printf ("%d\n", st->vbr_drift);*/
1451
Jean-Marc Valin9faf7402010-12-04 10:27:22 -05001452 if (st->constrained_vbr && st->vbr_reservoir < 0)
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001453 {
1454 /* We're under the min value -- increase rate */
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001455 int adjust = (-st->vbr_reservoir)/(8<<BITRES);
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001456 /* Unless we're just coding silence */
1457 nbAvailableBytes += silence?0:adjust;
Gregory Maxwellfac6c982010-10-28 15:00:37 -04001458 st->vbr_reservoir = 0;
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001459 /*printf ("+%d\n", adjust);*/
1460 }
Gregory Maxwelld85018c2011-01-13 14:38:24 -05001461 nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
Jean-Marc Valinbd5d54a2009-10-20 00:25:31 -04001462 /* This moves the raw bits to take into account the new compressed size */
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001463 ec_enc_shrink(enc, nbCompressedBytes);
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001464 }
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001465 if (C==2)
1466 {
1467 int effectiveRate;
1468
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001469 /* Always use MS for 2.5 ms frames until we can do a better analysis */
1470 if (LM!=0)
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -05001471 dual_stereo = stereo_analysis(st->mode, X, LM, N);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08001472
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001473 /* Account for coarse energy */
Jean-Marc Valine5e9aa72010-12-02 16:09:51 -05001474 effectiveRate = (8*effectiveBytes - 80)>>LM;
1475
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001476 /* effectiveRate in kb/s */
1477 effectiveRate = 2*effectiveRate/5;
1478 if (effectiveRate<35)
Jean-Marc Valin6cbfbc32010-12-14 11:53:39 -05001479 intensity = 8;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001480 else if (effectiveRate<50)
1481 intensity = 12;
1482 else if (effectiveRate<68)
1483 intensity = 16;
1484 else if (effectiveRate<84)
1485 intensity = 18;
1486 else if (effectiveRate<102)
1487 intensity = 19;
1488 else if (effectiveRate<130)
1489 intensity = 20;
1490 else
1491 intensity = 100;
1492 intensity = IMIN(st->end,IMAX(st->start, intensity));
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05001493 }
1494
Jean-Marc Valinbe04f5a2010-08-07 21:42:03 -04001495 /* Bit allocation */
1496 ALLOC(fine_quant, st->mode->nbEBands, int);
1497 ALLOC(pulses, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04001498 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valincb7a2a32008-02-11 16:44:48 +11001499
Timothy B. Terriberry285bc372011-02-06 13:29:00 -08001500 /* bits = packet size - where we are - safety*/
Gregory Maxwell75d27802011-08-30 14:02:41 -04001501 bits = (((opus_int32)nbCompressedBytes*8)<<BITRES) - ec_tell_frac(enc) - 1;
1502 anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08001503 bits -= anti_collapse_rsv;
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08001504 codedBands = compute_allocation(st->mode, st->start, st->end, offsets, cap,
Timothy B. Terriberry948d27c2011-01-31 12:28:12 -08001505 alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
1506 fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands);
Jean-Marc Valindfd6e712010-12-09 23:23:34 -05001507 st->lastCodedBands = codedBands;
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -05001508
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -05001509 quant_fine_energy(st->mode, st->start, st->end, oldBandE, error, fine_quant, enc, C);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04001510
Jean-Marc Valin7b5a0862010-07-29 15:01:24 +02001511#ifdef MEASURE_NORM_MSE
Jean-Marc Valin44092242010-07-29 18:32:54 +02001512 float X0[3000];
1513 float bandE0[60];
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04001514 c=0; do
Jean-Marc Valin44092242010-07-29 18:32:54 +02001515 for (i=0;i<N;i++)
1516 X0[i+c*N] = X[i+c*N];
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001517 while (++c<C);
Jean-Marc Valin44092242010-07-29 18:32:54 +02001518 for (i=0;i<C*st->mode->nbEBands;i++)
Jean-Marc Valin7b5a0862010-07-29 15:01:24 +02001519 bandE0[i] = bandE[i];
1520#endif
1521
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001522 /* Residual quantisation */
Jean-Marc Valin7e983192011-02-01 18:00:29 -05001523 ALLOC(collapse_masks, C*st->mode->nbEBands, unsigned char);
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08001524 quant_all_bands(1, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, collapse_masks,
Gregory Maxwelld830d082011-08-15 16:05:40 -04001525 bandE, pulses, shortBlocks, st->spread_decision, dual_stereo, intensity, tf_res,
Timothy B. Terriberry948d27c2011-01-31 12:28:12 -08001526 nbCompressedBytes*(8<<BITRES)-anti_collapse_rsv, balance, enc, LM, codedBands, &st->rng);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001527
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08001528 if (anti_collapse_rsv > 0)
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05001529 {
1530 anti_collapse_on = st->consec_transient<2;
Jean-Marc Valinf334c822011-08-11 16:21:58 -04001531#ifdef FUZZING
1532 anti_collapse_on = rand()&0x1;
1533#endif
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05001534 ec_enc_bits(enc, anti_collapse_on, 1);
1535 }
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001536 quant_energy_finalise(st->mode, st->start, st->end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C);
Jean-Marc Valin39710532009-06-09 00:10:32 -04001537
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001538 if (silence)
1539 {
1540 for (i=0;i<C*st->mode->nbEBands;i++)
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001541 oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
Gregory Maxwell8b631f22011-01-26 20:19:01 -05001542 }
1543
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001544#ifdef RESYNTH
Jean-Marc Valin37ab9c62008-11-08 09:14:38 -05001545 /* Re-synthesis of the coded audio if required */
Jean-Marc Valin18ddc022008-02-22 14:24:50 +11001546 {
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001547 celt_sig *out_mem[2];
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001548 celt_sig *overlap_mem[2];
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001549
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001550 log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);
Jean-Marc Valin4b000c32011-01-26 20:30:21 -05001551 if (silence)
1552 {
1553 for (i=0;i<C*st->mode->nbEBands;i++)
1554 bandE[i] = 0;
1555 }
Jean-Marc Valinbc272de2010-08-02 09:41:31 -04001556
1557#ifdef MEASURE_NORM_MSE
1558 measure_norm_mse(st->mode, X, X0, bandE, bandE0, M, N, C);
1559#endif
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05001560 if (anti_collapse_on)
1561 {
Timothy B. Terriberry682b6cf2011-01-31 13:34:54 -08001562 anti_collapse(st->mode, X, collapse_masks, LM, C, CC, N,
Jean-Marc Valin63fb61f2011-01-20 22:52:55 -05001563 st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng);
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05001564 }
Jean-Marc Valinbc272de2010-08-02 09:41:31 -04001565
Jean-Marc Valin88619552009-10-04 21:35:36 -04001566 /* Synthesis */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04001567 denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
Jean-Marc Valin88619552009-10-04 21:35:36 -04001568
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001569 OPUS_MOVE(st->syn_mem[0], st->syn_mem[0]+N, MAX_PERIOD);
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001570 if (CC==2)
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001571 OPUS_MOVE(st->syn_mem[1], st->syn_mem[1]+N, MAX_PERIOD);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001572
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001573 c=0; do
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001574 for (i=0;i<M*st->mode->eBands[st->start];i++)
1575 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001576 while (++c<C);
1577 c=0; do
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001578 for (i=M*st->mode->eBands[st->end];i<N;i++)
1579 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001580 while (++c<C);
Jean-Marc Valin3b0df0d2010-07-16 15:55:30 -04001581
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001582 if (CC==2&&C==1)
1583 {
1584 for (i=0;i<N;i++)
1585 freq[N+i] = freq[i];
1586 }
1587
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001588 out_mem[0] = st->syn_mem[0]+MAX_PERIOD;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001589 if (CC==2)
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001590 out_mem[1] = st->syn_mem[1]+MAX_PERIOD;
Jean-Marc Valin0d8eaa32010-08-27 14:57:37 -04001591
Gregory Maxwella45724e2011-07-29 11:53:45 -04001592 overlap_mem[0] = prefilter_mem+CC*COMBFILTER_MAXPERIOD;
1593 if (CC==2)
1594 overlap_mem[1] = overlap_mem[0] + st->overlap;
Jean-Marc Valine0ce2cf2010-08-26 23:58:08 -04001595
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001596 compute_inv_mdcts(st->mode, shortBlocks, freq, out_mem, overlap_mem, CC, LM);
Jean-Marc Valine12017e2009-10-03 13:57:31 -04001597
Gregory Maxwell9743bf32010-11-04 20:45:09 -04001598 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001599 st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
1600 st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD);
Jean-Marc Valin64805fd2011-02-12 00:50:53 -05001601 comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, st->mode->shortMdctSize,
Jean-Marc Valina14e86d2011-02-11 16:27:27 -05001602 st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset,
1603 st->mode->window, st->overlap);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001604 if (LM!=0)
Jean-Marc Valin64805fd2011-02-12 00:50:53 -05001605 comb_filter(out_mem[c]+st->mode->shortMdctSize, out_mem[c]+st->mode->shortMdctSize, st->prefilter_period, pitch_index, N-st->mode->shortMdctSize,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001606 st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset,
1607 st->mode->window, st->mode->overlap);
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001608 } while (++c<CC);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001609
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001610 deemphasis(out_mem, (opus_val16*)pcm, N, CC, st->upsample, st->mode->preemph, st->preemph_memD);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001611 st->prefilter_period_old = st->prefilter_period;
1612 st->prefilter_gain_old = st->prefilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001613 st->prefilter_tapset_old = st->prefilter_tapset;
Jean-Marc Valind9b95652008-08-31 23:34:47 -04001614 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001615#endif
1616
1617 st->prefilter_period = pitch_index;
1618 st->prefilter_gain = gain1;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001619 st->prefilter_tapset = prefilter_tapset;
Jean-Marc Valina14e86d2011-02-11 16:27:27 -05001620#ifdef RESYNTH
1621 if (LM!=0)
1622 {
1623 st->prefilter_period_old = st->prefilter_period;
1624 st->prefilter_gain_old = st->prefilter_gain;
1625 st->prefilter_tapset_old = st->prefilter_tapset;
1626 }
1627#endif
Gregory Maxwell54547f12009-02-16 18:56:44 -05001628
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001629 if (CC==2&&C==1) {
1630 for (i=0;i<st->mode->nbEBands;i++)
1631 oldBandE[st->mode->nbEBands+i]=oldBandE[i];
1632 }
1633
Jean-Marc Valin5677e342011-01-13 16:15:53 -05001634 /* In case start or end were to change */
Jean-Marc Valin5c2ac2b2011-01-22 14:48:20 -05001635 c=0; do
1636 {
1637 for (i=0;i<st->start;i++)
1638 oldBandE[c*st->mode->nbEBands+i]=0;
1639 for (i=st->end;i<st->mode->nbEBands;i++)
1640 oldBandE[c*st->mode->nbEBands+i]=0;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001641 } while (++c<CC);
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05001642 if (!isTransient)
1643 {
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001644 for (i=0;i<CC*st->mode->nbEBands;i++)
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05001645 oldLogE2[i] = oldLogE[i];
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001646 for (i=0;i<CC*st->mode->nbEBands;i++)
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05001647 oldLogE[i] = oldBandE[i];
Jean-Marc Valin47e905d2011-01-27 18:05:47 -05001648 } else {
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001649 for (i=0;i<CC*st->mode->nbEBands;i++)
Jean-Marc Valin47e905d2011-01-27 18:05:47 -05001650 oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]);
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05001651 }
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05001652 if (isTransient)
1653 st->consec_transient++;
1654 else
1655 st->consec_transient=0;
Jean-Marc Valin63fb61f2011-01-20 22:52:55 -05001656 st->rng = enc->rng;
Jean-Marc Valin5677e342011-01-13 16:15:53 -05001657
Jean-Marc Valin30d51252010-06-21 17:55:28 -04001658 /* If there's any room left (can only happen for very high rates),
Jean-Marc Valin13a7c262011-01-26 10:58:33 -05001659 it's already filled with zeros */
Jean-Marc Valin4794f2e2010-05-19 11:56:57 -04001660 ec_enc_done(enc);
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04001661
Gregory Maxwellfd17eab2011-10-04 03:31:45 -04001662#ifdef CUSTOM_MODES
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05001663 if (st->signalling)
1664 nbCompressedBytes++;
Gregory Maxwellfd17eab2011-10-04 03:31:45 -04001665#endif
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05001666
Jean-Marc Valin8600f692008-02-29 15:14:12 +11001667 RESTORE_STACK;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08001668 if (ec_get_error(enc))
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001669 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin9d785af2010-07-18 09:42:05 -04001670 else
1671 return nbCompressedBytes;
Jean-Marc Valin8ebd3452007-11-29 20:17:32 +11001672}
1673
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001674
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001675#ifdef CUSTOM_MODES
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001676
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001677#ifdef FIXED_POINT
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001678int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001679{
1680 return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
1681}
1682
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001683#ifndef DISABLE_FLOAT_API
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001684int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001685{
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05001686 int j, ret, C, N;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001687 VARDECL(opus_int16, in);
Jean-Marc Valin7e983192011-02-01 18:00:29 -05001688 ALLOC_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001689
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001690 if (pcm==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001691 return OPUS_BAD_ARG;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001692
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001693 C = CHANNELS(st->channels);
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05001694 N = frame_size;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001695 ALLOC(in, C*N, opus_int16);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001696
1697 for (j=0;j<C*N;j++)
1698 in[j] = FLOAT2INT16(pcm[j]);
1699
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001700 ret=celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001701#ifdef RESYNTH
1702 for (j=0;j<C*N;j++)
1703 ((float*)pcm)[j]=in[j]*(1.f/32768.f);
1704#endif
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001705 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001706 return ret;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001707}
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001708#endif /* DISABLE_FLOAT_API */
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001709#else
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001710
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001711int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001712{
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05001713 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001714 VARDECL(celt_sig, in);
Jean-Marc Valin7e983192011-02-01 18:00:29 -05001715 ALLOC_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04001716
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001717 if (pcm==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001718 return OPUS_BAD_ARG;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04001719
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001720 C=CHANNELS(st->channels);
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05001721 N=frame_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04001722 ALLOC(in, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001723 for (j=0;j<C*N;j++) {
1724 in[j] = SCALEOUT(pcm[j]);
1725 }
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001726
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001727 ret = celt_encode_with_ec(st,in,frame_size,compressed,nbCompressedBytes, NULL);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001728#ifdef RESYNTH
1729 for (j=0;j<C*N;j++)
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001730 ((opus_int16*)pcm)[j] = FLOAT2INT16(in[j]);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001731#endif
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04001732 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04001733 return ret;
1734}
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +11001735
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001736int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001737{
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001738 return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
Jean-Marc Valind56c6102010-05-07 20:30:22 -04001739}
1740
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001741#endif
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001742
1743#endif /* CUSTOM_MODES */
1744
1745int opus_custom_encoder_ctl(CELTEncoder * restrict st, int request, ...)
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001746{
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001747 va_list ap;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04001748
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001749 va_start(ap, request);
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001750 switch (request)
1751 {
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001752 case OPUS_SET_COMPLEXITY_REQUEST:
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001753 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001754 int value = va_arg(ap, opus_int32);
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001755 if (value<0 || value>10)
1756 goto bad_arg;
Jean-Marc Valin1213ba52010-08-31 17:03:13 -04001757 st->complexity = value;
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001758 }
1759 break;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001760 case CELT_SET_START_BAND_REQUEST:
1761 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001762 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001763 if (value<0 || value>=st->mode->nbEBands)
1764 goto bad_arg;
1765 st->start = value;
1766 }
1767 break;
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001768 case CELT_SET_END_BAND_REQUEST:
1769 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001770 opus_int32 value = va_arg(ap, opus_int32);
Timothy B. Terriberry8893e532010-12-30 08:56:49 -08001771 if (value<1 || value>st->mode->nbEBands)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04001772 goto bad_arg;
1773 st->end = value;
1774 }
1775 break;
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001776 case CELT_SET_PREDICTION_REQUEST:
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001777 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001778 int value = va_arg(ap, opus_int32);
Gregory Maxwell2dd3d322009-06-05 14:05:51 -04001779 if (value<0 || value>2)
Gregory Maxwell98046ca2008-12-13 20:42:03 -05001780 goto bad_arg;
Jean-Marc Valind539c6b2011-02-03 13:36:03 -05001781 st->disable_pf = value<=1;
1782 st->force_intra = value==0;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001783 }
1784 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001785 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
Jean-Marc Valin69653882011-04-21 10:41:13 -04001786 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001787 int value = va_arg(ap, opus_int32);
Jean-Marc Valin69653882011-04-21 10:41:13 -04001788 if (value<0 || value>100)
1789 goto bad_arg;
1790 st->loss_rate = value;
1791 }
1792 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001793 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
Jean-Marc Valin79b34eb2010-12-05 17:22:06 -05001794 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001795 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin79b34eb2010-12-05 17:22:06 -05001796 st->constrained_vbr = value;
1797 }
1798 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001799 case OPUS_SET_VBR_REQUEST:
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001800 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001801 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001802 st->vbr = value;
1803 }
1804 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001805 case OPUS_SET_BITRATE_REQUEST:
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001806 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001807 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin663a7fe2011-09-06 14:05:19 -04001808 if (value<=500 && value!=OPUS_BITRATE_MAX)
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001809 goto bad_arg;
Jean-Marc Valin8430a752011-02-03 23:54:37 -05001810 value = IMIN(value, 260000*st->channels);
Jean-Marc Valin7bb26e12011-02-01 17:04:27 -05001811 st->bitrate = value;
Gregory Maxwell888d8ce2009-05-21 04:21:53 -04001812 }
1813 break;
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001814 case CELT_SET_CHANNELS_REQUEST:
1815 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001816 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin00a98f52011-01-31 11:19:03 -05001817 if (value<1 || value>2)
1818 goto bad_arg;
1819 st->stream_channels = value;
1820 }
1821 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001822 case OPUS_RESET_STATE:
John Ridges454d1d02009-05-21 22:38:39 -04001823 {
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001824 OPUS_CLEAR((char*)&st->ENCODER_RESET_START,
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001825 opus_custom_encoder_get_size(st->mode, st->channels)-
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04001826 ((char*)&st->ENCODER_RESET_START - (char*)st));
Jean-Marc Valin30165bb2010-12-03 14:35:59 -05001827 st->vbr_offset = 0;
John Ridges454d1d02009-05-21 22:38:39 -04001828 st->delayedIntra = 1;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08001829 st->spread_decision = SPREAD_NORMAL;
Gregory Maxwellec8008b2011-08-30 16:50:01 -04001830 st->tonal_average = 256;
John Ridges454d1d02009-05-21 22:38:39 -04001831 }
1832 break;
Gregory Maxwellfd17eab2011-10-04 03:31:45 -04001833#ifdef CUSTOM_MODES
Jean-Marc Valin0b405d12011-02-04 01:03:42 -05001834 case CELT_SET_INPUT_CLIPPING_REQUEST:
1835 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001836 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin0b405d12011-02-04 01:03:42 -05001837 st->clip = value;
1838 }
1839 break;
Gregory Maxwellfd17eab2011-10-04 03:31:45 -04001840#endif
Jean-Marc Valinc3086a92011-03-21 13:26:03 -04001841 case CELT_SET_SIGNALLING_REQUEST:
1842 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001843 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinc3086a92011-03-21 13:26:03 -04001844 st->signalling = value;
1845 }
1846 break;
1847 case CELT_GET_MODE_REQUEST:
1848 {
1849 const CELTMode ** value = va_arg(ap, const CELTMode**);
1850 if (value==0)
1851 goto bad_arg;
1852 *value=st->mode;
1853 }
1854 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001855 case OPUS_GET_FINAL_RANGE_REQUEST:
Jean-Marc Valin06cee2b2011-08-19 16:11:41 -04001856 {
1857 opus_uint32 * value = va_arg(ap, opus_uint32 *);
1858 if (value==0)
1859 goto bad_arg;
1860 *value=st->rng;
1861 }
1862 break;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001863 default:
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001864 goto bad_request;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001865 }
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001866 va_end(ap);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001867 return OPUS_OK;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001868bad_arg:
1869 va_end(ap);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001870 return OPUS_BAD_ARG;
Jean-Marc Valinb6f90612008-10-05 22:39:13 -04001871bad_request:
1872 va_end(ap);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001873 return OPUS_UNIMPLEMENTED;
Jean-Marc Valinc18fb1d2008-09-30 07:36:54 -04001874}
1875
Jean-Marc Valin56522ad2009-06-05 17:17:25 -04001876/**********************************************************************/
1877/* */
1878/* DECODER */
1879/* */
1880/**********************************************************************/
Jean-Marc Valineafbdd52009-04-27 19:35:09 -04001881#define DECODE_BUFFER_SIZE 2048
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001882
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04001883/** Decoder state
Jean-Marc Valin276de722008-02-20 17:45:51 +11001884 @brief Decoder state
1885 */
Jean-Marc Valin242da532011-09-05 20:53:33 -04001886struct OpusCustomDecoder {
1887 const OpusCustomMode *mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001888 int overlap;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001889 int channels;
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05001890 int stream_channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001891
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001892 int downsample;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001893 int start, end;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05001894 int signalling;
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04001895
1896 /* Everything beyond this point gets cleared on a reset */
Jean-Marc Valin63fb61f2011-01-20 22:52:55 -05001897#define DECODER_RESET_START rng
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04001898
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04001899 opus_uint32 rng;
Jean-Marc Valinef20e392011-03-18 15:34:11 -04001900 int error;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001901 int last_pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001902 int loss_count;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04001903 int postfilter_period;
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05001904 int postfilter_period_old;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001905 opus_val16 postfilter_gain;
1906 opus_val16 postfilter_gain_old;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05001907 int postfilter_tapset;
1908 int postfilter_tapset_old;
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001909
1910 celt_sig preemph_memD[2];
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04001911
Jean-Marc Valinca8b9922010-08-27 16:23:03 -04001912 celt_sig _decode_mem[1]; /* Size = channels*(DECODE_BUFFER_SIZE+mode->overlap) */
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001913 /* opus_val16 lpc[], Size = channels*LPC_ORDER */
1914 /* opus_val16 oldEBands[], Size = 2*mode->nbEBands */
1915 /* opus_val16 oldLogE[], Size = 2*mode->nbEBands */
1916 /* opus_val16 oldLogE2[], Size = 2*mode->nbEBands */
1917 /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001918};
1919
Jean-Marc Valin8cf29f02011-01-30 23:38:28 -05001920int celt_decoder_get_size(int channels)
1921{
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001922 const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
1923 return opus_custom_decoder_get_size(mode, channels);
Jean-Marc Valin8cf29f02011-01-30 23:38:28 -05001924}
1925
Gregory Maxwellafc8d532011-09-28 15:13:26 -04001926OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001927{
1928 int size = sizeof(struct CELTDecoder)
1929 + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001930 + channels*LPC_ORDER*sizeof(opus_val16)
1931 + 4*2*mode->nbEBands*sizeof(opus_val16);
Jean-Marc Valin02a35272010-08-27 16:00:01 -04001932 return size;
1933}
1934
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001935#ifdef CUSTOM_MODES
1936CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
Jean-Marc Valinc97b2582011-01-28 23:07:32 -05001937{
Jean-Marc Valin875f8db2011-08-31 16:43:08 -04001938 int ret;
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001939 CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
1940 ret = opus_custom_decoder_init(st, mode, channels);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001941 if (ret != OPUS_OK)
Jean-Marc Valind6c3d3c2011-01-30 10:23:40 -05001942 {
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001943 opus_custom_decoder_destroy(st);
Jean-Marc Valind6c3d3c2011-01-30 10:23:40 -05001944 st = NULL;
1945 }
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001946 if (error)
1947 *error = ret;
Jean-Marc Valind6c3d3c2011-01-30 10:23:40 -05001948 return st;
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -04001949}
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001950#endif /* CUSTOM_MODES */
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001951
Gregory Maxwell64a35412011-09-02 10:31:17 -04001952int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels)
Jean-Marc Valinc97b2582011-01-28 23:07:32 -05001953{
Jean-Marc Valin875f8db2011-08-31 16:43:08 -04001954 int ret;
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001955 ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001956 if (ret != OPUS_OK)
Jean-Marc Valin875f8db2011-08-31 16:43:08 -04001957 return ret;
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001958 st->downsample = resampling_factor(sampling_rate);
1959 if (st->downsample==0)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001960 return OPUS_BAD_ARG;
Jean-Marc Valin875f8db2011-08-31 16:43:08 -04001961 else
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001962 return OPUS_OK;
Jean-Marc Valinc97b2582011-01-28 23:07:32 -05001963}
1964
Gregory Maxwellafc8d532011-09-28 15:13:26 -04001965OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
Jean-Marc Valin7cfb7302010-08-27 16:54:33 -04001966{
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04001967 if (channels < 0 || channels > 2)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001968 return OPUS_BAD_ARG;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11001969
Gregory Maxwell17169992009-06-04 15:15:34 -04001970 if (st==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001971 return OPUS_ALLOC_FAIL;
Jean-Marc Valinece94a02009-10-16 07:30:14 -04001972
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001973 OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
Jean-Marc Valin6d3829f2010-08-27 17:52:38 -04001974
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001975 st->mode = mode;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001976 st->overlap = mode->overlap;
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05001977 st->stream_channels = st->channels = channels;
Jean-Marc Valina5431bf2008-01-03 20:53:01 +11001978
Jean-Marc Valin913a1742011-01-29 10:00:20 -05001979 st->downsample = 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001980 st->start = 0;
Jean-Marc Valin8952c452010-07-16 21:48:44 -04001981 st->end = st->mode->effEBands;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05001982 st->signalling = 1;
Jean-Marc Valin5f961462010-05-19 13:38:10 -04001983
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04001984 st->loss_count = 0;
Gregory Maxwell17169992009-06-04 15:15:34 -04001985
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001986 return OPUS_OK;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001987}
1988
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001989#ifdef CUSTOM_MODES
1990void opus_custom_decoder_destroy(CELTDecoder *st)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001991{
Jean-Marc Valin07f88402011-08-29 15:08:51 -04001992 opus_free(st);
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001993}
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001994#endif /* CUSTOM_MODES */
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11001995
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04001996static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pcm, int N, int LM)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11001997{
Jean-Marc Valin04752672010-05-05 07:21:21 -04001998 int c;
Jean-Marc Valin0bb05bc2008-02-20 13:43:40 +11001999 int pitch_index;
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002000 int overlap = st->mode->overlap;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002001 opus_val16 fade = Q15ONE;
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10002002 int i, len;
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04002003 const int C = CHANNELS(st->channels);
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10002004 int offset;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002005 celt_sig *out_mem[2];
2006 celt_sig *decode_mem[2];
2007 celt_sig *overlap_mem[2];
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002008 opus_val16 *lpc;
2009 opus_val32 *out_syn[2];
2010 opus_val16 *oldBandE, *oldLogE2, *backgroundLogE;
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002011 int plc=1;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11002012 SAVE_STACK;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002013
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002014 c=0; do {
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002015 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap);
2016 out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD;
2017 overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002018 } while (++c<C);
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002019 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*C);
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002020 oldBandE = lpc+C*LPC_ORDER;
2021 oldLogE2 = oldBandE + C*st->mode->nbEBands;
2022 backgroundLogE = oldLogE2 + C*st->mode->nbEBands;
2023
2024 out_syn[0] = out_mem[0]+MAX_PERIOD-N;
2025 if (C==2)
2026 out_syn[1] = out_mem[1]+MAX_PERIOD-N;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002027
Jean-Marc Valin24c9cda2008-05-02 10:34:07 +10002028 len = N+st->mode->overlap;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002029
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002030 if (st->loss_count >= 5)
2031 {
2032 VARDECL(celt_sig, freq);
2033 VARDECL(celt_norm, X);
2034 VARDECL(celt_ener, bandE);
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002035 opus_uint32 seed;
Jean-Marc Valin1a8bf372011-03-16 22:03:15 -04002036 int effEnd;
2037
2038 effEnd = st->end;
2039 if (effEnd > st->mode->effEBands)
2040 effEnd = st->mode->effEBands;
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002041
2042 ALLOC(freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
2043 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
2044 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
2045
2046 log2Amp(st->mode, st->start, st->end, bandE, backgroundLogE, C);
2047
2048 seed = st->rng;
Timothy B. Terriberry115fa352011-03-02 15:28:08 -08002049 for (c=0;c<C;c++)
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002050 {
Jean-Marc Valin1a8bf372011-03-16 22:03:15 -04002051 for (i=0;i<(st->mode->eBands[st->start]<<LM);i++)
2052 X[c*N+i] = 0;
Timothy B. Terriberry115fa352011-03-02 15:28:08 -08002053 for (i=0;i<st->mode->effEBands;i++)
2054 {
2055 int j;
2056 int boffs;
2057 int blen;
2058 boffs = N*c+(st->mode->eBands[i]<<LM);
2059 blen = (st->mode->eBands[i+1]-st->mode->eBands[i])<<LM;
2060 for (j=0;j<blen;j++)
2061 {
Jean-Marc Valin7fc2fbd2011-09-01 13:40:39 -04002062 seed = celt_lcg_rand(seed);
Gregory Maxwellec8008b2011-08-30 16:50:01 -04002063 X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
Timothy B. Terriberry115fa352011-03-02 15:28:08 -08002064 }
2065 renormalise_vector(X+boffs, blen, Q15ONE);
2066 }
Jean-Marc Valin1a8bf372011-03-16 22:03:15 -04002067 for (i=(st->mode->eBands[st->end]<<LM);i<N;i++)
2068 X[c*N+i] = 0;
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002069 }
2070 st->rng = seed;
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002071
Timothy B. Terriberry115fa352011-03-02 15:28:08 -08002072 denormalise_bands(st->mode, X, freq, bandE, st->mode->effEBands, C, 1<<LM);
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002073
Jean-Marc Valin1a8bf372011-03-16 22:03:15 -04002074 c=0; do
2075 for (i=0;i<st->mode->eBands[st->start]<<LM;i++)
2076 freq[c*N+i] = 0;
2077 while (++c<C);
2078 c=0; do {
2079 int bound = st->mode->eBands[effEnd]<<LM;
2080 if (st->downsample!=1)
2081 bound = IMIN(bound, N/st->downsample);
2082 for (i=bound;i<N;i++)
2083 freq[c*N+i] = 0;
2084 } while (++c<C);
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002085 compute_inv_mdcts(st->mode, 0, freq, out_syn, overlap_mem, C, LM);
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002086 plc = 0;
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002087 } else if (st->loss_count == 0)
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04002088 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002089 opus_val16 pitch_buf[DECODE_BUFFER_SIZE>>1];
Jean-Marc Valin5f3d1af2011-05-13 17:24:25 -04002090 /* Corresponds to a min pitch of 67 Hz. It's possible to save CPU in this
2091 search by using only part of the decode buffer */
2092 int poffset = 720;
2093 pitch_downsample(decode_mem, pitch_buf, DECODE_BUFFER_SIZE, C);
2094 /* Max pitch is 100 samples (480 Hz) */
2095 pitch_search(pitch_buf+((poffset)>>1), pitch_buf, DECODE_BUFFER_SIZE-poffset,
2096 poffset-100, &pitch_index);
2097 pitch_index = poffset-pitch_index;
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04002098 st->last_pitch_index = pitch_index;
2099 } else {
2100 pitch_index = st->last_pitch_index;
Jean-Marc Valineafd8a72011-01-23 00:24:45 -05002101 fade = QCONST16(.8f,15);
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04002102 }
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11002103
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002104 if (plc)
2105 {
2106 c=0; do {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002107 VARDECL(opus_val32, e);
2108 opus_val16 exc[MAX_PERIOD];
2109 opus_val32 ac[LPC_ORDER+1];
2110 opus_val16 decay = 1;
2111 opus_val32 S1=0;
Gregory Maxwell06d57b22011-08-01 22:02:25 -04002112 opus_val16 mem[LPC_ORDER]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002113
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002114 ALLOC(e, MAX_PERIOD+2*st->mode->overlap, opus_val32);
Jean-Marc Valinf54a0a32011-05-13 17:36:31 -04002115
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002116 offset = MAX_PERIOD-pitch_index;
2117 for (i=0;i<MAX_PERIOD;i++)
2118 exc[i] = ROUND16(out_mem[c][i], SIG_SHIFT);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05002119
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002120 if (st->loss_count == 0)
2121 {
2122 _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
2123 LPC_ORDER, MAX_PERIOD);
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05002124
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002125 /* Noise floor -40 dB */
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04002126#ifdef FIXED_POINT
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002127 ac[0] += SHR32(ac[0],13);
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04002128#else
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002129 ac[0] *= 1.0001f;
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04002130#endif
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002131 /* Lag windowing */
2132 for (i=1;i<=LPC_ORDER;i++)
2133 {
2134 /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04002135#ifdef FIXED_POINT
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002136 ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04002137#else
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002138 ac[i] -= ac[i]*(.008f*i)*(.008f*i);
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -04002139#endif
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002140 }
2141
2142 _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
2143 }
2144 for (i=0;i<LPC_ORDER;i++)
2145 mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
Jean-Marc Valin7fc2fbd2011-09-01 13:40:39 -04002146 celt_fir(exc, lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002147 /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
2148 /* Check if the waveform is decaying (and if so how fast) */
2149 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002150 opus_val32 E1=1, E2=1;
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002151 int period;
2152 if (pitch_index <= MAX_PERIOD/2)
2153 period = pitch_index;
2154 else
2155 period = MAX_PERIOD/2;
2156 for (i=0;i<period;i++)
2157 {
2158 E1 += SHR32(MULT16_16(exc[MAX_PERIOD-period+i],exc[MAX_PERIOD-period+i]),8);
2159 E2 += SHR32(MULT16_16(exc[MAX_PERIOD-2*period+i],exc[MAX_PERIOD-2*period+i]),8);
2160 }
2161 if (E1 > E2)
2162 E1 = E2;
2163 decay = celt_sqrt(frac_div32(SHR(E1,1),E2));
Jean-Marc Valin5a0fae52009-12-14 21:19:37 -05002164 }
2165
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002166 /* Copy excitation, taking decay into account */
2167 for (i=0;i<len+st->mode->overlap;i++)
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002168 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002169 opus_val16 tmp;
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002170 if (offset+i >= MAX_PERIOD)
2171 {
2172 offset -= pitch_index;
2173 decay = MULT16_16_Q15(decay, decay);
2174 }
2175 e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT);
2176 tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT);
2177 S1 += SHR32(MULT16_16(tmp,tmp),8);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002178 }
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002179 for (i=0;i<LPC_ORDER;i++)
2180 mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
2181 for (i=0;i<len+st->mode->overlap;i++)
2182 e[i] = MULT16_32_Q15(fade, e[i]);
Jean-Marc Valin7fc2fbd2011-09-01 13:40:39 -04002183 celt_iir(e, lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002184
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002185 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002186 opus_val32 S2=0;
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05002187 for (i=0;i<len+overlap;i++)
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002188 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002189 opus_val16 tmp = ROUND16(e[i],SIG_SHIFT);
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002190 S2 += SHR32(MULT16_16(tmp,tmp),8);
2191 }
2192 /* This checks for an "explosion" in the synthesis */
2193#ifdef FIXED_POINT
2194 if (!(S1 > SHR32(S2,2)))
2195#else
2196 /* Float test is written this way to catch NaNs at the same time */
2197 if (!(S1 > 0.2f*S2))
2198#endif
2199 {
2200 for (i=0;i<len+overlap;i++)
2201 e[i] = 0;
2202 } else if (S1 < S2)
2203 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002204 opus_val16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002205 for (i=0;i<len+overlap;i++)
2206 e[i] = MULT16_32_Q15(ratio, e[i]);
2207 }
Jean-Marc Valin07fed1b2009-12-28 07:59:42 -05002208 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002209
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002210 /* Apply post-filter to the MDCT overlap of the previous frame */
2211 comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap,
2212 st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
2213 NULL, 0);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002214
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002215 for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
2216 out_mem[c][i] = out_mem[c][N+i];
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002217
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002218 /* Apply TDAC to the concealed audio so that it blends with the
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002219 previous and next frames */
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002220 for (i=0;i<overlap/2;i++)
2221 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002222 opus_val32 tmp;
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002223 tmp = MULT16_32_Q15(st->mode->window[i], e[N+overlap-1-i]) +
2224 MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i ]);
2225 out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp);
2226 out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp);
2227 }
2228 for (i=0;i<N;i++)
2229 out_mem[c][MAX_PERIOD-N+i] = e[i];
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002230
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002231 /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */
2232 comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap,
2233 -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
2234 NULL, 0);
Jean-Marc Valin8430a752011-02-03 23:54:37 -05002235 for (i=0;i<overlap;i++)
2236 out_mem[c][MAX_PERIOD+i] = e[i];
2237 } while (++c<C);
2238 }
Jean-Marc Valin1677aa92007-12-08 01:13:34 +11002239
Jean-Marc Valin913a1742011-01-29 10:00:20 -05002240 deemphasis(out_syn, pcm, N, C, st->downsample, st->mode->preemph, st->preemph_memD);
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002241
Jean-Marc Valin0f0da992009-08-12 21:34:01 -04002242 st->loss_count++;
2243
Jean-Marc Valin8600f692008-02-29 15:14:12 +11002244 RESTORE_STACK;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11002245}
2246
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002247int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, opus_val16 * restrict pcm, int frame_size, ec_dec *dec)
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11002248{
Jean-Marc Valin0695a5f2010-08-27 11:33:18 -04002249 int c, i, N;
Timothy B. Terriberry320cf2e2010-12-17 05:52:06 -08002250 int spread_decision;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002251 opus_int32 bits;
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002252 ec_dec _dec;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04002253 VARDECL(celt_sig, freq);
Jean-Marc Valin234969c2009-10-17 22:12:42 -04002254 VARDECL(celt_norm, X);
2255 VARDECL(celt_ener, bandE);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002256 VARDECL(int, fine_quant);
2257 VARDECL(int, pulses);
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08002258 VARDECL(int, cap);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002259 VARDECL(int, offsets);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04002260 VARDECL(int, fine_priority);
Jean-Marc Valin163b76e2010-05-27 23:56:53 -04002261 VARDECL(int, tf_res);
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08002262 VARDECL(unsigned char, collapse_masks);
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002263 celt_sig *out_mem[2];
2264 celt_sig *decode_mem[2];
2265 celt_sig *overlap_mem[2];
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04002266 celt_sig *out_syn[2];
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002267 opus_val16 *lpc;
2268 opus_val16 *oldBandE, *oldLogE, *oldLogE2, *backgroundLogE;
Jean-Marc Valinc890b582008-08-01 22:26:49 -04002269
Jean-Marc Valin9d1decd2008-06-17 13:28:13 +10002270 int shortBlocks;
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04002271 int isTransient;
Jean-Marc Valin05ed03e2009-04-29 07:44:13 -04002272 int intra_ener;
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002273 const int CC = CHANNELS(st->channels);
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002274 int LM, M;
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04002275 int effEnd;
Jean-Marc Valinb801da52010-09-28 14:56:20 -04002276 int codedBands;
Jean-Marc Valinf1fea662010-10-09 22:58:52 -04002277 int alloc_trim;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002278 int postfilter_pitch;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002279 opus_val16 postfilter_gain;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05002280 int intensity=0;
Jean-Marc Valine65978f2010-12-02 13:46:48 -05002281 int dual_stereo=0;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002282 opus_int32 total_bits;
2283 opus_int32 balance;
2284 opus_int32 tell;
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002285 int dynalloc_logp;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002286 int postfilter_tapset;
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08002287 int anti_collapse_rsv;
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05002288 int anti_collapse_on=0;
Jean-Marc Valinde79c372011-01-26 09:24:33 -05002289 int silence;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002290 int C = CHANNELS(st->stream_channels);
Jean-Marc Valinf62b3bb2011-03-09 11:56:29 -05002291 ALLOC_STACK;
Jean-Marc Valin44ffd5a2008-02-22 00:39:25 +11002292
Jean-Marc Valin913a1742011-01-29 10:00:20 -05002293 frame_size *= st->downsample;
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002294
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002295 c=0; do {
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002296 decode_mem[c] = st->_decode_mem + c*(DECODE_BUFFER_SIZE+st->overlap);
2297 out_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE-MAX_PERIOD;
2298 overlap_mem[c] = decode_mem[c]+DECODE_BUFFER_SIZE;
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002299 } while (++c<CC);
Jean-Marc Valinff5f7222011-07-29 18:59:12 -04002300 lpc = (opus_val16*)(st->_decode_mem+(DECODE_BUFFER_SIZE+st->overlap)*CC);
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002301 oldBandE = lpc+LPC_ORDER;
2302 oldLogE = oldBandE + 2*st->mode->nbEBands;
2303 oldLogE2 = oldLogE + 2*st->mode->nbEBands;
2304 backgroundLogE = oldLogE2 + 2*st->mode->nbEBands;
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002305
Gregory Maxwellfd17eab2011-10-04 03:31:45 -04002306#ifdef CUSTOM_MODES
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002307 if (st->signalling && data!=NULL)
2308 {
Jean-Marc Valind6bf19d2011-03-21 07:06:09 -04002309 int data0=data[0];
2310 /* Convert "standard mode" to Opus header */
2311 if (st->mode->Fs==48000 && st->mode->shortMdctSize==120)
2312 {
2313 data0 = fromOpus(data0);
2314 if (data0<0)
Jean-Marc Valin331e9fe2011-09-06 14:30:19 -04002315 return OPUS_INVALID_PACKET;
Jean-Marc Valind6bf19d2011-03-21 07:06:09 -04002316 }
2317 st->end = IMAX(1, st->mode->effEBands-2*(data0>>5));
2318 LM = (data0>>3)&0x3;
2319 C = 1 + ((data0>>2)&0x1);
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002320 data++;
2321 len--;
2322 if (LM>st->mode->maxLM)
Jean-Marc Valin331e9fe2011-09-06 14:30:19 -04002323 return OPUS_INVALID_PACKET;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002324 if (frame_size < st->mode->shortMdctSize<<LM)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002325 return OPUS_BUFFER_TOO_SMALL;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002326 else
2327 frame_size = st->mode->shortMdctSize<<LM;
2328 } else {
Gregory Maxwellfd17eab2011-10-04 03:31:45 -04002329#else
2330 {
2331#endif
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002332 for (LM=0;LM<=st->mode->maxLM;LM++)
2333 if (st->mode->shortMdctSize<<LM==frame_size)
2334 break;
2335 if (LM>st->mode->maxLM)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002336 return OPUS_BAD_ARG;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002337 }
2338 M=1<<LM;
2339
2340 if (len<0 || len>1275 || pcm==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002341 return OPUS_BAD_ARG;
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002342
Jean-Marc Valin04752672010-05-05 07:21:21 -04002343 N = M*st->mode->shortMdctSize;
Jean-Marc Valin01417232008-03-03 13:59:55 +11002344
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04002345 effEnd = st->end;
2346 if (effEnd > st->mode->effEBands)
2347 effEnd = st->mode->effEBands;
2348
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002349 ALLOC(freq, IMAX(CC,C)*N, celt_sig); /**< Interleaved signal MDCTs */
2350 ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
2351 ALLOC(bandE, st->mode->nbEBands*C, celt_ener);
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002352 c=0; do
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002353 for (i=0;i<M*st->mode->eBands[st->start];i++)
2354 X[c*N+i] = 0;
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002355 while (++c<C);
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002356 c=0; do
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04002357 for (i=M*st->mode->eBands[effEnd];i<N;i++)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04002358 X[c*N+i] = 0;
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002359 while (++c<C);
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002360
Jean-Marc Valin65d35a32011-01-26 22:04:59 -05002361 if (data == NULL || len<=1)
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11002362 {
Jean-Marc Valin017fa852010-05-06 22:11:48 -04002363 celt_decode_lost(st, pcm, N, LM);
Jean-Marc Valin8600f692008-02-29 15:14:12 +11002364 RESTORE_STACK;
Jean-Marc Valin37e788c2011-03-16 20:56:28 -04002365 return frame_size/st->downsample;
Jean-Marc Valinfb83fb42007-12-08 00:56:04 +11002366 }
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002367
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002368 if (dec == NULL)
2369 {
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002370 ec_dec_init(&_dec,(unsigned char*)data,len);
Jean-Marc Valinf5e2e322010-05-19 12:05:02 -04002371 dec = &_dec;
2372 }
Jean-Marc Valin6b95d8f2010-06-21 21:39:44 -04002373
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002374 if (C<CC)
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002375 {
2376 for (i=0;i<st->mode->nbEBands;i++)
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002377 oldBandE[i]=MAX16(oldBandE[i],oldBandE[st->mode->nbEBands+i]);
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002378 }
2379
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002380 total_bits = len*8;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002381 tell = ec_tell(dec);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002382
Jean-Marc Valina0653ed2011-07-05 13:18:59 -04002383 if (tell >= total_bits)
2384 silence = 1;
2385 else if (tell==1)
Jean-Marc Valin65d35a32011-01-26 22:04:59 -05002386 silence = ec_dec_bit_logp(dec, 15);
2387 else
2388 silence = 0;
Jean-Marc Valinde79c372011-01-26 09:24:33 -05002389 if (silence)
2390 {
Jean-Marc Valin13a7c262011-01-26 10:58:33 -05002391 /* Pretend we've read all the remaining bits */
Jean-Marc Valinde79c372011-01-26 09:24:33 -05002392 tell = len*8;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002393 dec->nbits_total+=tell-ec_tell(dec);
Jean-Marc Valinde79c372011-01-26 09:24:33 -05002394 }
2395
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002396 postfilter_gain = 0;
2397 postfilter_pitch = 0;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002398 postfilter_tapset = 0;
Jean-Marc Valinef986e42011-02-03 15:47:10 -05002399 if (st->start==0 && tell+16 <= total_bits)
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002400 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002401 if(ec_dec_bit_logp(dec, 1))
2402 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002403 int qg, octave;
2404 octave = ec_dec_uint(dec, 6);
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002405 postfilter_pitch = (16<<octave)+ec_dec_bits(dec, 4+octave)-1;
Jean-Marc Valinef986e42011-02-03 15:47:10 -05002406 qg = ec_dec_bits(dec, 3);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002407 if (ec_tell(dec)+2<=total_bits)
Jean-Marc Valinef986e42011-02-03 15:47:10 -05002408 postfilter_tapset = ec_dec_icdf(dec, tapset_icdf, 2);
2409 postfilter_gain = QCONST16(.09375f,15)*(qg+1);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002410 }
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002411 tell = ec_tell(dec);
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002412 }
2413
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002414 if (LM > 0 && tell+3 <= total_bits)
2415 {
Timothy B. Terriberrye86fb262010-12-17 14:50:19 -08002416 isTransient = ec_dec_bit_logp(dec, 3);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002417 tell = ec_tell(dec);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002418 }
Jean-Marc Valinf9fdbff2010-09-05 21:02:38 -04002419 else
2420 isTransient = 0;
Jean-Marc Valin017001a2010-08-05 15:42:50 -04002421
Jean-Marc Valin3b918ba2010-05-05 00:02:26 -04002422 if (isTransient)
2423 shortBlocks = M;
2424 else
2425 shortBlocks = 0;
2426
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002427 /* Decode the global flags (first symbols in the stream) */
2428 intra_ener = tell+3<=total_bits ? ec_dec_bit_logp(dec, 3) : 0;
2429 /* Get band energies */
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -05002430 unquant_coarse_energy(st->mode, st->start, st->end, oldBandE,
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002431 intra_ener, dec, C, LM);
2432
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -04002433 ALLOC(tf_res, st->mode->nbEBands, int);
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -05002434 tf_decode(st->start, st->end, isTransient, tf_res, LM, dec);
Jean-Marc Valin0a571ef2010-06-05 23:12:19 -04002435
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002436 tell = ec_tell(dec);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002437 spread_decision = SPREAD_NORMAL;
2438 if (tell+4 <= total_bits)
2439 spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04002440
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002441 ALLOC(pulses, st->mode->nbEBands, int);
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08002442 ALLOC(cap, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002443 ALLOC(offsets, st->mode->nbEBands, int);
Jean-Marc Valin52cb5fb2009-06-10 08:08:55 -04002444 ALLOC(fine_priority, st->mode->nbEBands, int);
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002445
Timothy B. Terriberryce6d0902011-02-01 17:41:12 -08002446 init_caps(st->mode,cap,LM,C);
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08002447
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002448 dynalloc_logp = 6;
2449 total_bits<<=BITRES;
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002450 tell = ec_tell_frac(dec);
Timothy B. Terriberryd6f61572010-12-30 09:04:16 -08002451 for (i=st->start;i<st->end;i++)
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002452 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002453 int width, quanta;
2454 int dynalloc_loop_logp;
2455 int boost;
2456 width = C*(st->mode->eBands[i+1]-st->mode->eBands[i])<<LM;
2457 /* quanta is 6 bits, but no more than 1 bit/sample
2458 and no less than 1/8 bit/sample */
2459 quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
2460 dynalloc_loop_logp = dynalloc_logp;
2461 boost = 0;
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08002462 while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002463 {
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002464 int flag;
2465 flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002466 tell = ec_tell_frac(dec);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002467 if (!flag)
2468 break;
2469 boost += quanta;
2470 total_bits -= quanta;
2471 dynalloc_loop_logp = 1;
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002472 }
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002473 offsets[i] = boost;
2474 /* Making dynalloc more likely */
2475 if (boost>0)
2476 dynalloc_logp = IMAX(2, dynalloc_logp-1);
Jean-Marc Valind74c8512010-09-29 17:39:54 -04002477 }
Jean-Marc Valin6775de32008-08-02 08:14:42 -04002478
Jean-Marc Valin9099bc32010-08-07 21:50:01 -04002479 ALLOC(fine_quant, st->mode->nbEBands, int);
Timothy B. Terriberry76469c62011-01-07 09:18:34 -08002480 alloc_trim = tell+(6<<BITRES) <= total_bits ?
2481 ec_dec_icdf(dec, trim_icdf, 7) : 5;
Jean-Marc Valin4f177e82010-11-26 10:32:03 -05002482
Gregory Maxwell75d27802011-08-30 14:02:41 -04002483 bits = (((opus_int32)len*8)<<BITRES) - ec_tell_frac(dec) - 1;
2484 anti_collapse_rsv = isTransient&&LM>=2&&bits>=((LM+2)<<BITRES) ? (1<<BITRES) : 0;
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08002485 bits -= anti_collapse_rsv;
Timothy B. Terriberryc5643072011-01-29 12:57:18 -08002486 codedBands = compute_allocation(st->mode, st->start, st->end, offsets, cap,
Timothy B. Terriberry948d27c2011-01-31 12:28:12 -08002487 alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
2488 fine_quant, fine_priority, C, LM, dec, 0, 0);
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002489
Jean-Marc Valinc39bb8a2011-01-26 10:50:55 -05002490 unquant_fine_energy(st->mode, st->start, st->end, oldBandE, fine_quant, dec, C);
Jean-Marc Valin827f9312008-05-06 23:21:55 +10002491
Jean-Marc Valin8cbea172010-08-05 15:22:57 -04002492 /* Decode fixed codebook */
Jean-Marc Valin7e983192011-02-01 18:00:29 -05002493 ALLOC(collapse_masks, C*st->mode->nbEBands, unsigned char);
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08002494 quant_all_bands(0, st->mode, st->start, st->end, X, C==2 ? X+N : NULL, collapse_masks,
Gregory Maxwelld830d082011-08-15 16:05:40 -04002495 NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
Timothy B. Terriberry948d27c2011-01-31 12:28:12 -08002496 len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng);
Jean-Marc Valin746b2a82010-05-14 22:12:33 -04002497
Timothy B. Terriberry21af73e2011-01-19 16:30:03 -08002498 if (anti_collapse_rsv > 0)
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05002499 {
2500 anti_collapse_on = ec_dec_bits(dec, 1);
2501 }
2502
Jean-Marc Valine3e2c262011-01-26 13:09:53 -05002503 unquant_energy_finalise(st->mode, st->start, st->end, oldBandE,
Timothy B. Terriberrya093f4d2011-02-03 14:22:15 -08002504 fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
Jean-Marc Valin30d51252010-06-21 17:55:28 -04002505
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05002506 if (anti_collapse_on)
Gregory Maxwellb288c502011-08-12 14:22:16 -04002507 anti_collapse(st->mode, X, collapse_masks, LM, C, CC, N,
Jean-Marc Valin63fb61f2011-01-20 22:52:55 -05002508 st->start, st->end, oldBandE, oldLogE, oldLogE2, pulses, st->rng);
Jean-Marc Valin87efe1d2011-01-18 14:44:04 -05002509
Jean-Marc Valin02a35272010-08-27 16:00:01 -04002510 log2Amp(st->mode, st->start, st->end, bandE, oldBandE, C);
Jean-Marc Valinbc272de2010-08-02 09:41:31 -04002511
Jean-Marc Valinde79c372011-01-26 09:24:33 -05002512 if (silence)
2513 {
2514 for (i=0;i<C*st->mode->nbEBands;i++)
2515 {
2516 bandE[i] = 0;
Gregory Maxwell8b631f22011-01-26 20:19:01 -05002517 oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
Jean-Marc Valinde79c372011-01-26 09:24:33 -05002518 }
2519 }
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11002520 /* Synthesis */
Jean-Marc Valin85f41b22010-07-16 18:12:45 -04002521 denormalise_bands(st->mode, X, freq, bandE, effEnd, C, M);
Jean-Marc Valina4833ff2008-01-10 15:34:00 +11002522
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04002523 OPUS_MOVE(decode_mem[0], decode_mem[0]+N, DECODE_BUFFER_SIZE-N);
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002524 if (CC==2)
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04002525 OPUS_MOVE(decode_mem[1], decode_mem[1]+N, DECODE_BUFFER_SIZE-N);
Jean-Marc Valin88619552009-10-04 21:35:36 -04002526
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002527 c=0; do
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002528 for (i=0;i<M*st->mode->eBands[st->start];i++)
2529 freq[c*N+i] = 0;
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002530 while (++c<C);
Jean-Marc Valin913a1742011-01-29 10:00:20 -05002531 c=0; do {
2532 int bound = M*st->mode->eBands[effEnd];
2533 if (st->downsample!=1)
2534 bound = IMIN(bound, N/st->downsample);
Jean-Marc Valin23340e22011-02-03 23:21:00 -05002535 for (i=bound;i<N;i++)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04002536 freq[c*N+i] = 0;
Jean-Marc Valin913a1742011-01-29 10:00:20 -05002537 } while (++c<C);
Jean-Marc Valin3a0bc3d2010-02-21 15:10:22 -05002538
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002539 out_syn[0] = out_mem[0]+MAX_PERIOD-N;
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002540 if (CC==2)
Jean-Marc Valin6d131082010-08-27 15:15:32 -04002541 out_syn[1] = out_mem[1]+MAX_PERIOD-N;
Jean-Marc Valinf67b4472010-08-27 01:32:40 -04002542
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002543 if (CC==2&&C==1)
2544 {
2545 for (i=0;i<N;i++)
2546 freq[N+i] = freq[i];
2547 }
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002548 if (CC==1&&C==2)
2549 {
2550 for (i=0;i<N;i++)
2551 freq[i] = HALF32(ADD32(freq[i],freq[N+i]));
2552 }
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002553
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11002554 /* Compute inverse MDCTs */
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002555 compute_inv_mdcts(st->mode, shortBlocks, freq, out_syn, overlap_mem, CC, LM);
Jean-Marc Valinffa13472007-12-10 16:54:17 +11002556
Gregory Maxwell9743bf32010-11-04 20:45:09 -04002557 c=0; do {
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002558 st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
2559 st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
Jean-Marc Valin64805fd2011-02-12 00:50:53 -05002560 comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, st->mode->shortMdctSize,
Jean-Marc Valina14e86d2011-02-11 16:27:27 -05002561 st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
2562 st->mode->window, st->overlap);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002563 if (LM!=0)
Jean-Marc Valin64805fd2011-02-12 00:50:53 -05002564 comb_filter(out_syn[c]+st->mode->shortMdctSize, out_syn[c]+st->mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-st->mode->shortMdctSize,
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002565 st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
2566 st->mode->window, st->mode->overlap);
Jean-Marc Valin64805fd2011-02-12 00:50:53 -05002567
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002568 } while (++c<CC);
Jean-Marc Valin70d30ff2010-12-13 13:50:29 -05002569 st->postfilter_period_old = st->postfilter_period;
2570 st->postfilter_gain_old = st->postfilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002571 st->postfilter_tapset_old = st->postfilter_tapset;
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002572 st->postfilter_period = postfilter_pitch;
2573 st->postfilter_gain = postfilter_gain;
Jean-Marc Valindfa847a2011-01-17 11:37:08 -05002574 st->postfilter_tapset = postfilter_tapset;
Jean-Marc Valina14e86d2011-02-11 16:27:27 -05002575 if (LM!=0)
2576 {
2577 st->postfilter_period_old = st->postfilter_period;
2578 st->postfilter_gain_old = st->postfilter_gain;
2579 st->postfilter_tapset_old = st->postfilter_tapset;
2580 }
Jean-Marc Valin35095c62010-11-04 13:24:44 -04002581
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002582 if (C==1) {
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002583 for (i=0;i<st->mode->nbEBands;i++)
2584 oldBandE[st->mode->nbEBands+i]=oldBandE[i];
2585 }
2586
Jean-Marc Valin5677e342011-01-13 16:15:53 -05002587 /* In case start or end were to change */
Jean-Marc Valin5c2ac2b2011-01-22 14:48:20 -05002588 c=0; do
2589 {
2590 for (i=0;i<st->start;i++)
2591 oldBandE[c*st->mode->nbEBands+i]=0;
2592 for (i=st->end;i<st->mode->nbEBands;i++)
2593 oldBandE[c*st->mode->nbEBands+i]=0;
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002594 } while (++c<2);
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05002595 if (!isTransient)
2596 {
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002597 for (i=0;i<2*st->mode->nbEBands;i++)
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05002598 oldLogE2[i] = oldLogE[i];
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002599 for (i=0;i<2*st->mode->nbEBands;i++)
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05002600 oldLogE[i] = oldBandE[i];
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002601 for (i=0;i<2*st->mode->nbEBands;i++)
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05002602 backgroundLogE[i] = MIN16(backgroundLogE[i] + M*QCONST16(0.001f,DB_SHIFT), oldBandE[i]);
Jean-Marc Valin47e905d2011-01-27 18:05:47 -05002603 } else {
Jean-Marc Valin9dec74d2011-03-28 01:39:41 -04002604 for (i=0;i<2*st->mode->nbEBands;i++)
Jean-Marc Valin47e905d2011-01-27 18:05:47 -05002605 oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]);
Jean-Marc Valin9ce95e02011-01-25 19:12:06 -05002606 }
Jean-Marc Valin63fb61f2011-01-20 22:52:55 -05002607 st->rng = dec->rng;
Jean-Marc Valin5677e342011-01-13 16:15:53 -05002608
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002609 deemphasis(out_syn, pcm, N, CC, st->downsample, st->mode->preemph, st->preemph_memD);
Jean-Marc Valine14fe902009-12-11 00:07:31 -05002610 st->loss_count = 0;
Jean-Marc Valin8600f692008-02-29 15:14:12 +11002611 RESTORE_STACK;
Jean-Marc Valinef20e392011-03-18 15:34:11 -04002612 if (ec_tell(dec) > 8*len)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002613 return OPUS_INTERNAL_ERROR;
Jean-Marc Valinef20e392011-03-18 15:34:11 -04002614 if(ec_get_error(dec))
2615 st->error = 1;
2616 return frame_size/st->downsample;
Jean-Marc Valin269d40a2007-12-07 11:29:45 +11002617}
2618
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002619
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002620#ifdef CUSTOM_MODES
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002621
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002622#ifdef FIXED_POINT
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002623int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002624{
2625 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
2626}
2627
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002628#ifndef DISABLE_FLOAT_API
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002629int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002630{
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05002631 int j, ret, C, N;
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002632 VARDECL(opus_int16, out);
Jean-Marc Valin7e983192011-02-01 18:00:29 -05002633 ALLOC_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04002634
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002635 if (pcm==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002636 return OPUS_BAD_ARG;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002637
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04002638 C = CHANNELS(st->channels);
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05002639 N = frame_size;
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002640
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002641 ALLOC(out, C*N, opus_int16);
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002642 ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL);
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002643 if (ret>0)
2644 for (j=0;j<C*ret;j++)
Jean-Marc Valinae01e112010-08-03 21:43:41 -04002645 pcm[j]=out[j]*(1.f/32768.f);
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002646
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04002647 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002648 return ret;
2649}
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002650#endif /* DISABLE_FLOAT_API */
2651
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002652#else
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002653
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002654int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002655{
2656 return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
2657}
2658
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002659int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002660{
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05002661 int j, ret, C, N;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04002662 VARDECL(celt_sig, out);
Jean-Marc Valin7e983192011-02-01 18:00:29 -05002663 ALLOC_STACK;
Gregory Maxwell17169992009-06-04 15:15:34 -04002664
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002665 if (pcm==NULL)
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002666 return OPUS_BAD_ARG;
Gregory Maxwell0719f6f2009-07-09 17:07:24 -04002667
Jean-Marc Valin80ed1472009-10-15 21:45:32 -04002668 C = CHANNELS(st->channels);
Jean-Marc Valin713d7a42011-01-31 13:41:01 -05002669 N = frame_size;
Jean-Marc Valin234969c2009-10-17 22:12:42 -04002670 ALLOC(out, C*N, celt_sig);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002671
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002672 ret=celt_decode_with_ec(st, data, len, out, frame_size, NULL);
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002673
Jean-Marc Valine6acfe02011-03-11 16:31:24 -05002674 if (ret>0)
2675 for (j=0;j<C*ret;j++)
Jean-Marc Valinb1e017f2010-07-18 21:20:35 -04002676 pcm[j] = FLOAT2INT16 (out[j]);
Gregory Maxwell71d39ad2011-07-30 00:00:29 -04002677
Wessel Lubberhuizen33ba6cc2008-10-03 07:09:29 -04002678 RESTORE_STACK;
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002679 return ret;
2680}
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002681
Gregory Maxwell5f2a74b2008-08-11 23:50:07 -04002682#endif
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002683#endif /* CUSTOM_MODES */
John Ridges454d1d02009-05-21 22:38:39 -04002684
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002685int opus_custom_decoder_ctl(CELTDecoder * restrict st, int request, ...)
John Ridges454d1d02009-05-21 22:38:39 -04002686{
2687 va_list ap;
Gregory Maxwell17169992009-06-04 15:15:34 -04002688
John Ridges454d1d02009-05-21 22:38:39 -04002689 va_start(ap, request);
2690 switch (request)
2691 {
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002692 case CELT_SET_START_BAND_REQUEST:
2693 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002694 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin5f961462010-05-19 13:38:10 -04002695 if (value<0 || value>=st->mode->nbEBands)
2696 goto bad_arg;
2697 st->start = value;
2698 }
2699 break;
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04002700 case CELT_SET_END_BAND_REQUEST:
2701 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002702 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwell1928f8d2011-02-08 22:32:56 -05002703 if (value<1 || value>st->mode->nbEBands)
Jean-Marc Valin525d7cf2010-07-13 14:14:16 -04002704 goto bad_arg;
2705 st->end = value;
2706 }
2707 break;
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002708 case CELT_SET_CHANNELS_REQUEST:
2709 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002710 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinf1916a12011-01-31 10:51:30 -05002711 if (value<1 || value>2)
2712 goto bad_arg;
2713 st->stream_channels = value;
2714 }
Jean-Marc Valindd2973d2011-03-11 17:46:02 -05002715 break;
Jean-Marc Valinef20e392011-03-18 15:34:11 -04002716 case CELT_GET_AND_CLEAR_ERROR_REQUEST:
2717 {
Jean-Marc Valin25f7f352011-09-14 09:50:06 -07002718 int *value = va_arg(ap, opus_int32*);
Jean-Marc Valinef20e392011-03-18 15:34:11 -04002719 if (value==NULL)
2720 goto bad_arg;
2721 *value=st->error;
2722 st->error = 0;
2723 }
2724 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002725 case OPUS_GET_LOOKAHEAD_REQUEST:
Jean-Marc Valinff96b162011-03-21 11:32:50 -04002726 {
Jean-Marc Valin25f7f352011-09-14 09:50:06 -07002727 int *value = va_arg(ap, opus_int32*);
Jean-Marc Valinff96b162011-03-21 11:32:50 -04002728 if (value==NULL)
2729 goto bad_arg;
2730 *value = st->overlap/st->downsample;
2731 }
2732 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002733 case OPUS_RESET_STATE:
John Ridges454d1d02009-05-21 22:38:39 -04002734 {
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04002735 OPUS_CLEAR((char*)&st->DECODER_RESET_START,
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002736 opus_custom_decoder_get_size(st->mode, st->channels)-
Jean-Marc Valinc09807d2010-08-27 17:17:50 -04002737 ((char*)&st->DECODER_RESET_START - (char*)st));
John Ridges454d1d02009-05-21 22:38:39 -04002738 }
2739 break;
Jean-Marc Valin25f7f352011-09-14 09:50:06 -07002740 case OPUS_GET_PITCH_REQUEST:
2741 {
2742 int *value = va_arg(ap, opus_int32*);
2743 if (value==NULL)
2744 goto bad_arg;
2745 *value = st->postfilter_period;
2746 }
2747 break;
Jean-Marc Valinc3086a92011-03-21 13:26:03 -04002748#ifdef OPUS_BUILD
2749 case CELT_GET_MODE_REQUEST:
2750 {
2751 const CELTMode ** value = va_arg(ap, const CELTMode**);
2752 if (value==0)
2753 goto bad_arg;
2754 *value=st->mode;
2755 }
2756 break;
2757 case CELT_SET_SIGNALLING_REQUEST:
2758 {
Jean-Marc Valind77d6a52011-07-29 17:33:06 -04002759 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinc3086a92011-03-21 13:26:03 -04002760 st->signalling = value;
2761 }
2762 break;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002763 case OPUS_GET_FINAL_RANGE_REQUEST:
Jean-Marc Valin06cee2b2011-08-19 16:11:41 -04002764 {
2765 opus_uint32 * value = va_arg(ap, opus_uint32 *);
2766 if (value==0)
2767 goto bad_arg;
2768 *value=st->rng;
2769 }
2770 break;
Jean-Marc Valinc3086a92011-03-21 13:26:03 -04002771#endif
John Ridges454d1d02009-05-21 22:38:39 -04002772 default:
2773 goto bad_request;
2774 }
2775 va_end(ap);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002776 return OPUS_OK;
John Ridges454d1d02009-05-21 22:38:39 -04002777bad_arg:
2778 va_end(ap);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002779 return OPUS_BAD_ARG;
John Ridges454d1d02009-05-21 22:38:39 -04002780bad_request:
2781 va_end(ap);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002782 return OPUS_UNIMPLEMENTED;
John Ridges454d1d02009-05-21 22:38:39 -04002783}
Jean-Marc Valinece94a02009-10-16 07:30:14 -04002784
Jean-Marc Valinf9265dd2011-09-01 13:46:18 -04002785
2786
2787const char *opus_strerror(int error)
2788{
2789 static const char *error_strings[8] = {
2790 "success",
2791 "invalid argument",
2792 "buffer too small",
2793 "internal error",
2794 "corrupted stream",
2795 "request not implemented",
2796 "invalid state",
2797 "memory allocation failed"
2798 };
2799 if (error > 0 || error < -7)
2800 return "unknown error";
2801 else
2802 return error_strings[-error];
2803}
2804
2805const char *opus_get_version_string(void)
2806{
2807 return "libopus " OPUS_VERSION
2808#ifdef FUZZING
2809 "-fuzzing"
2810#endif
2811 ;
2812}