blob: bb94ec1a729e98014e7d9f892aba706ecfb37644 [file] [log] [blame]
Jean-Marc Valin6696a142011-08-22 10:40:38 -04001/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
Jean-Marc Valinfbaabc12010-07-05 15:47:04 -04002 Written by Jean-Marc Valin and Koen Vos */
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04003/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
Jean-Marc Valin3e66e912010-06-30 14:16:14 -040015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Jean-Marc Valincb05e7c2012-04-20 16:40:24 -040018 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Jean-Marc Valin3e66e912010-06-30 14:16:14 -040020 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
Jean-Marc Valin24f36e02010-07-06 14:41:20 -040032#include <stdarg.h>
Jean-Marc Valin8ea67042011-03-11 17:49:10 -050033#include "celt.h"
Jean-Marc Valina0cbeca2010-07-08 11:27:20 -040034#include "entenc.h"
35#include "modes.h"
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070036#include "API.h"
Jean-Marc Valin222494f2011-08-17 15:53:37 -040037#include "stack_alloc.h"
38#include "float_cast.h"
Jean-Marc Valind9920f32011-08-19 13:00:49 -040039#include "opus.h"
40#include "arch.h"
Jean-Marc Valin66b7fe02013-12-09 13:54:41 -050041#include "pitch.h"
Jean-Marc Valin6696a142011-08-22 10:40:38 -040042#include "opus_private.h"
Jean-Marc Valin07f88402011-08-29 15:08:51 -040043#include "os_support.h"
Aurélien Zanellicd4c8242013-05-31 15:07:00 +020044#include "cpu_support.h"
Jean-Marc Valinc5880fe2012-07-05 01:28:45 -040045#include "analysis.h"
46#include "mathops.h"
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070047#include "tuning_parameters.h"
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040048#ifdef FIXED_POINT
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070049#include "fixed/structs_FIX.h"
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040050#else
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070051#include "float/structs_FLP.h"
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040052#endif
53
Jean-Marc Valind9920f32011-08-19 13:00:49 -040054#define MAX_ENCODER_BUFFER 480
55
Felicia Lim33f18a22016-05-16 15:52:44 +020056#ifndef DISABLE_FLOAT_API
57#define PSEUDO_SNR_THRESHOLD 316.23f /* 10^(25/10) */
58#endif
59
Jean-Marc Valind865fe62013-03-11 11:35:10 -040060typedef struct {
61 opus_val32 XX, XY, YY;
62 opus_val16 smoothed_width;
63 opus_val16 max_follower;
64} StereoWidthState;
65
Jean-Marc Valind9920f32011-08-19 13:00:49 -040066struct OpusEncoder {
67 int celt_enc_offset;
68 int silk_enc_offset;
69 silk_EncControlStruct silk_mode;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040070 int application;
Jean-Marc Valin927488b2011-08-30 20:09:22 -040071 int channels;
72 int delay_compensation;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -040073 int force_channels;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040074 int signal_type;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040075 int user_bandwidth;
Jean-Marc Valin9ba17432011-10-24 22:41:18 -040076 int max_bandwidth;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -040077 int user_forced_mode;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040078 int voice_ratio;
Gregory Maxwell64a35412011-09-02 10:31:17 -040079 opus_int32 Fs;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040080 int use_vbr;
81 int vbr_constraint;
Jean-Marc Valin49583ed2012-11-22 13:11:43 -050082 int variable_duration;
Jean-Marc Valin8fdf2af2011-09-10 21:56:34 -040083 opus_int32 bitrate_bps;
84 opus_int32 user_bitrate_bps;
Jean-Marc Valin7509fdb2012-12-20 22:48:35 -050085 int lsb_depth;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040086 int encoder_buffer;
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -040087 int lfe;
Jean-Marc Valinfa73e752015-12-30 14:21:34 -050088 int arch;
Felicia Lime1bce7b2016-07-20 13:37:13 +020089 int use_dtx; /* general DTX for both SILK and CELT */
Ralph Giles9e3872a2015-12-30 15:27:02 -080090#ifndef DISABLE_FLOAT_API
91 TonalityAnalysisState analysis;
92#endif
Jean-Marc Valin927488b2011-08-30 20:09:22 -040093
94#define OPUS_ENCODER_RESET_START stream_channels
95 int stream_channels;
Jean-Marc Valin8fdf2af2011-09-10 21:56:34 -040096 opus_int16 hybrid_stereo_width_Q14;
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040097 opus_int32 variable_HP_smth2_Q15;
Jean-Marc Valinf68799b2012-07-12 17:36:11 -040098 opus_val16 prev_HB_gain;
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040099 opus_val32 hp_mem[4];
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400100 int mode;
101 int prev_mode;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400102 int prev_channels;
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400103 int prev_framesize;
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400104 int bandwidth;
Jean-Marc Valin691f6f92016-05-31 20:49:41 -0400105 /* Bandwidth determined automatically from the rate (before any other adjustment) */
106 int auto_bandwidth;
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -0400107 int silk_bw_switch;
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400108 /* Sampling rate (at the API level) */
Jean-Marc Valind9920f32011-08-19 13:00:49 -0400109 int first;
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -0400110 opus_val16 * energy_masking;
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400111 StereoWidthState width_mem;
Jean-Marc Valind9920f32011-08-19 13:00:49 -0400112 opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2];
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400113#ifndef DISABLE_FLOAT_API
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500114 int detected_bandwidth;
Felicia Lim36481342016-05-16 15:29:53 +0200115 int nb_no_activity_frames;
Felicia Lim33f18a22016-05-16 15:52:44 +0200116 opus_val32 peak_signal_energy;
Jean-Marc Valine9c353a2011-11-14 17:58:29 +0800117#endif
Felicia Lim0962cbe2016-10-27 17:03:36 -0700118 int nonfinal_frame; /* current frame is not the final in a packet */
Gregory Maxwell64a35412011-09-02 10:31:17 -0400119 opus_uint32 rangeFinal;
Jean-Marc Valind9920f32011-08-19 13:00:49 -0400120};
121
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400122/* Transition tables for the voice and music. First column is the
Jean-Marc Valin9edde422011-05-05 15:30:44 -0400123 middle (memoriless) threshold. The second column is the hysteresis
124 (difference with the middle) */
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400125static const opus_int32 mono_voice_bandwidth_thresholds[8] = {
Jean-Marc Valinde1f92c2016-06-02 15:50:22 -0400126 10000, 1000, /* NB<->MB */
127 11000, 1000, /* MB<->WB */
128 13500, 1000, /* WB<->SWB */
129 14000, 2000, /* SWB<->FB */
Jean-Marc Valin09c67662011-05-04 22:34:53 -0400130};
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400131static const opus_int32 mono_music_bandwidth_thresholds[8] = {
Jean-Marc Valinde1f92c2016-06-02 15:50:22 -0400132 10000, 1000, /* NB<->MB */
133 11000, 1000, /* MB<->WB */
134 13500, 1000, /* WB<->SWB */
135 14000, 2000, /* SWB<->FB */
Jean-Marc Valin09c67662011-05-04 22:34:53 -0400136};
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400137static const opus_int32 stereo_voice_bandwidth_thresholds[8] = {
Jean-Marc Valinde1f92c2016-06-02 15:50:22 -0400138 10000, 1000, /* NB<->MB */
139 11000, 1000, /* MB<->WB */
140 13500, 1000, /* WB<->SWB */
141 14000, 2000, /* SWB<->FB */
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400142};
143static const opus_int32 stereo_music_bandwidth_thresholds[8] = {
Jean-Marc Valinde1f92c2016-06-02 15:50:22 -0400144 10000, 1000, /* NB<->MB */
145 11000, 1000, /* MB<->WB */
146 13500, 1000, /* WB<->SWB */
147 14000, 2000, /* SWB<->FB */
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400148};
149/* Threshold bit-rates for switching between mono and stereo */
Jean-Marc Valin8dcf4ac2015-11-27 19:10:24 -0500150static const opus_int32 stereo_voice_threshold = 24000;
151static const opus_int32 stereo_music_threshold = 24000;
Jean-Marc Valin09c67662011-05-04 22:34:53 -0400152
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400153/* Threshold bit-rate for switching between SILK/hybrid and CELT-only */
154static const opus_int32 mode_thresholds[2][2] = {
155 /* voice */ /* music */
Jean-Marc Valind94ed202013-11-24 01:59:43 -0500156 { 64000, 16000}, /* mono */
157 { 36000, 16000}, /* stereo */
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400158};
Jean-Marc Valinb5972382011-10-07 08:38:27 -0400159
Jean-Marc Valin2b011b62016-06-21 12:38:25 -0400160static const opus_int32 fec_thresholds[] = {
161 12000, 1000, /* NB */
162 14000, 1000, /* MB */
163 16000, 1000, /* WB */
164 20000, 1000, /* SWB */
165 22000, 1000, /* FB */
166};
167
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400168int opus_encoder_get_size(int channels)
169{
Ralph Giles641eea82011-08-02 10:06:59 -0700170 int silkEncSizeBytes, celtEncSizeBytes;
171 int ret;
Gregory Maxwellf451b332011-09-04 10:47:15 -0400172 if (channels<1 || channels > 2)
173 return 0;
Ralph Giles641eea82011-08-02 10:06:59 -0700174 ret = silk_Get_Encoder_Size( &silkEncSizeBytes );
Ralph Giles04cca282011-08-24 00:29:29 -0400175 if (ret)
Ralph Giles641eea82011-08-02 10:06:59 -0700176 return 0;
177 silkEncSizeBytes = align(silkEncSizeBytes);
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400178 celtEncSizeBytes = celt_encoder_get_size(channels);
179 return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes;
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400180}
181
Gregory Maxwell64a35412011-09-02 10:31:17 -0400182int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int application)
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400183{
Ralph Giles641eea82011-08-02 10:06:59 -0700184 void *silk_enc;
185 CELTEncoder *celt_enc;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500186 int err;
Ralph Giles641eea82011-08-02 10:06:59 -0700187 int ret, silkEncSizeBytes;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400188
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400189 if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)||
190 (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO
191 && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY))
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400192 return OPUS_BAD_ARG;
Jean-Marc Valind3358b12011-06-14 14:48:53 -0400193
Jean-Marc Valinbe89c392011-08-30 12:39:51 -0400194 OPUS_CLEAR((char*)st, opus_encoder_get_size(channels));
Jean-Marc Valind3358b12011-06-14 14:48:53 -0400195 /* Create SILK encoder */
196 ret = silk_Get_Encoder_Size( &silkEncSizeBytes );
Ralph Giles04cca282011-08-24 00:29:29 -0400197 if (ret)
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400198 return OPUS_BAD_ARG;
Ralph Giles04cca282011-08-24 00:29:29 -0400199 silkEncSizeBytes = align(silkEncSizeBytes);
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400200 st->silk_enc_offset = align(sizeof(OpusEncoder));
201 st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes;
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400202 silk_enc = (char*)st+st->silk_enc_offset;
203 celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
204
Jean-Marc Valinb3864582011-01-31 12:41:49 -0500205 st->stream_channels = st->channels = channels;
Jean-Marc Valinbcdfe632010-08-31 11:22:43 -0400206
207 st->Fs = Fs;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400208
Aurélien Zanellicd4c8242013-05-31 15:07:00 +0200209 st->arch = opus_select_arch();
210
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500211 ret = silk_InitEncoder( silk_enc, st->arch, &st->silk_mode );
Gregory Maxwelle03af442011-09-04 04:43:11 -0400212 if(ret)return OPUS_INTERNAL_ERROR;
Jean-Marc Valinae180902010-07-19 11:44:36 -0400213
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500214 /* default SILK parameters */
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400215 st->silk_mode.nChannelsAPI = channels;
216 st->silk_mode.nChannelsInternal = channels;
217 st->silk_mode.API_sampleRate = st->Fs;
218 st->silk_mode.maxInternalSampleRate = 16000;
219 st->silk_mode.minInternalSampleRate = 8000;
220 st->silk_mode.desiredInternalSampleRate = 16000;
221 st->silk_mode.payloadSize_ms = 20;
222 st->silk_mode.bitRate = 25000;
223 st->silk_mode.packetLossPercentage = 0;
Jean-Marc Valinf5645f52013-09-16 14:36:53 -0400224 st->silk_mode.complexity = 9;
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400225 st->silk_mode.useInBandFEC = 0;
226 st->silk_mode.useDTX = 0;
227 st->silk_mode.useCBR = 0;
Jean-Marc Valincbe93e22013-11-15 13:50:38 -0500228 st->silk_mode.reducedDependency = 0;
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400229
Jean-Marc Valinc5ea0742010-07-05 11:11:54 -0400230 /* Create CELT encoder */
Ralph Giles641eea82011-08-02 10:06:59 -0700231 /* Initialize CELT encoder */
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500232 err = celt_encoder_init(celt_enc, Fs, channels, st->arch);
Gregory Maxwelle03af442011-09-04 04:43:11 -0400233 if(err!=OPUS_OK)return OPUS_INTERNAL_ERROR;
234
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400235 celt_encoder_ctl(celt_enc, CELT_SET_SIGNALLING(0));
Jean-Marc Valinf5645f52013-09-16 14:36:53 -0400236 celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(st->silk_mode.complexity));
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400237
Jean-Marc Valin21452882011-09-09 14:57:43 -0400238 st->use_vbr = 1;
Jean-Marc Valin66820f32012-01-31 02:03:39 -0500239 /* Makes constrained VBR the default (safer for real-time use) */
240 st->vbr_constraint = 1;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400241 st->user_bitrate_bps = OPUS_AUTO;
Ralph Giles641eea82011-08-02 10:06:59 -0700242 st->bitrate_bps = 3000+Fs*channels;
Jean-Marc Valin69549ac2011-08-18 17:28:28 -0400243 st->application = application;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400244 st->signal_type = OPUS_AUTO;
245 st->user_bandwidth = OPUS_AUTO;
Jean-Marc Valin9ba17432011-10-24 22:41:18 -0400246 st->max_bandwidth = OPUS_BANDWIDTH_FULLBAND;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400247 st->force_channels = OPUS_AUTO;
248 st->user_forced_mode = OPUS_AUTO;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400249 st->voice_ratio = -1;
Ralph Giles641eea82011-08-02 10:06:59 -0700250 st->encoder_buffer = st->Fs/100;
Jean-Marc Valin7509fdb2012-12-20 22:48:35 -0500251 st->lsb_depth = 24;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500252 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400253
Timothy B. Terriberry554b3492014-10-03 21:49:57 -0700254 /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead
Koen Vosbf75c8e2011-12-13 14:47:31 -0500255 + 1.5 ms for SILK resamplers and stereo prediction) */
256 st->delay_compensation = st->Fs/250;
Jean-Marc Valinb5972382011-10-07 08:38:27 -0400257
Koen Vosbf75c8e2011-12-13 14:47:31 -0500258 st->hybrid_stereo_width_Q14 = 1 << 14;
Jean-Marc Valinf68799b2012-07-12 17:36:11 -0400259 st->prev_HB_gain = Q15ONE;
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700260 st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400261 st->first = 1;
262 st->mode = MODE_HYBRID;
263 st->bandwidth = OPUS_BANDWIDTH_FULLBAND;
264
Ralph Gilesd43445f2015-12-30 10:00:17 -0800265#ifndef DISABLE_FLOAT_API
266 tonality_analysis_init(&st->analysis);
267#endif
268
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400269 return OPUS_OK;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400270}
271
Jean-Marc Valin78291b22011-10-08 22:12:31 -0400272static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels)
Jean-Marc Valin421a6282011-08-18 14:32:16 -0400273{
274 int period;
275 unsigned char toc;
276 period = 0;
277 while (framerate < 400)
278 {
279 framerate <<= 1;
280 period++;
281 }
282 if (mode == MODE_SILK_ONLY)
283 {
Jean-Marc Valin78291b22011-10-08 22:12:31 -0400284 toc = (bandwidth-OPUS_BANDWIDTH_NARROWBAND)<<5;
Jean-Marc Valin421a6282011-08-18 14:32:16 -0400285 toc |= (period-2)<<3;
286 } else if (mode == MODE_CELT_ONLY)
287 {
288 int tmp = bandwidth-OPUS_BANDWIDTH_MEDIUMBAND;
289 if (tmp < 0)
290 tmp = 0;
291 toc = 0x80;
292 toc |= tmp << 5;
293 toc |= period<<3;
294 } else /* Hybrid */
295 {
296 toc = 0x60;
297 toc |= (bandwidth-OPUS_BANDWIDTH_SUPERWIDEBAND)<<4;
298 toc |= (period-2)<<3;
299 }
300 toc |= (channels==2)<<2;
301 return toc;
302}
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400303
304#ifndef FIXED_POINT
Diego Elio PettenĂ²d006b782012-09-10 01:48:22 -0700305static void silk_biquad_float(
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400306 const opus_val16 *in, /* I: Input signal */
307 const opus_int32 *B_Q28, /* I: MA coefficients [3] */
308 const opus_int32 *A_Q28, /* I: AR coefficients [2] */
309 opus_val32 *S, /* I/O: State vector [2] */
310 opus_val16 *out, /* O: Output signal */
311 const opus_int32 len, /* I: Signal length (must be even) */
312 int stride
313)
314{
315 /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
316 opus_int k;
317 opus_val32 vout;
318 opus_val32 inval;
319 opus_val32 A[2], B[3];
320
Gregory Maxwell37f56592012-07-17 17:40:55 -0400321 A[0] = (opus_val32)(A_Q28[0] * (1.f/((opus_int32)1<<28)));
322 A[1] = (opus_val32)(A_Q28[1] * (1.f/((opus_int32)1<<28)));
323 B[0] = (opus_val32)(B_Q28[0] * (1.f/((opus_int32)1<<28)));
324 B[1] = (opus_val32)(B_Q28[1] * (1.f/((opus_int32)1<<28)));
325 B[2] = (opus_val32)(B_Q28[2] * (1.f/((opus_int32)1<<28)));
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400326
327 /* Negate A_Q28 values and split in two parts */
328
329 for( k = 0; k < len; k++ ) {
330 /* S[ 0 ], S[ 1 ]: Q12 */
331 inval = in[ k*stride ];
332 vout = S[ 0 ] + B[0]*inval;
333
334 S[ 0 ] = S[1] - vout*A[0] + B[1]*inval;
335
Jean-Marc Valin03e82032013-08-12 14:47:14 -0400336 S[ 1 ] = - vout*A[1] + B[2]*inval + VERY_SMALL;
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400337
338 /* Scale back to Q0 and saturate */
339 out[ k*stride ] = vout;
340 }
341}
342#endif
343
344static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
345{
346 opus_int32 B_Q28[ 3 ], A_Q28[ 2 ];
347 opus_int32 Fc_Q19, r_Q28, r_Q22;
348
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700349 silk_assert( cutoff_Hz <= silk_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) );
350 Fc_Q19 = silk_DIV32_16( silk_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), Fs/1000 );
351 silk_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400352
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700353 r_Q28 = SILK_FIX_CONST( 1.0, 28 ) - silk_MUL( SILK_FIX_CONST( 0.92, 9 ), Fc_Q19 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400354
355 /* b = r * [ 1; -2; 1 ]; */
356 /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */
357 B_Q28[ 0 ] = r_Q28;
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700358 B_Q28[ 1 ] = silk_LSHIFT( -r_Q28, 1 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400359 B_Q28[ 2 ] = r_Q28;
360
361 /* -r * ( 2 - Fc * Fc ); */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700362 r_Q22 = silk_RSHIFT( r_Q28, 6 );
363 A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) );
364 A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400365
366#ifdef FIXED_POINT
367 silk_biquad_alt( in, B_Q28, A_Q28, hp_mem, out, len, channels );
368 if( channels == 2 ) {
369 silk_biquad_alt( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
370 }
371#else
372 silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels );
373 if( channels == 2 ) {
374 silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
375 }
376#endif
377}
378
Jean-Marc Valinac2e6232011-12-29 01:23:33 -0500379#ifdef FIXED_POINT
380static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
381{
382 int c, i;
383 int shift;
384
385 /* Approximates -round(log2(4.*cutoff_Hz/Fs)) */
386 shift=celt_ilog2(Fs/(cutoff_Hz*3));
387 for (c=0;c<channels;c++)
388 {
389 for (i=0;i<len;i++)
390 {
391 opus_val32 x, tmp, y;
Jean-Marc Valin096b2202016-08-21 15:53:35 -0400392 x = SHL32(EXTEND32(in[channels*i+c]), 14);
Jean-Marc Valinac2e6232011-12-29 01:23:33 -0500393 /* First stage */
394 tmp = x-hp_mem[2*c];
395 hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift);
396 /* Second stage */
397 y = tmp - hp_mem[2*c+1];
398 hp_mem[2*c+1] = hp_mem[2*c+1] + PSHR32(tmp - hp_mem[2*c+1], shift);
Jean-Marc Valin096b2202016-08-21 15:53:35 -0400399 out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 14), 32767));
Jean-Marc Valinac2e6232011-12-29 01:23:33 -0500400 }
401 }
402}
403
404#else
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500405static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
406{
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400407 int i;
408 float coef, coef2;
Ralph Giles027ec512012-10-23 10:49:18 -0700409 coef = 4.0f*cutoff_Hz/Fs;
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400410 coef2 = 1-coef;
411 if (channels==2)
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500412 {
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400413 float m0, m1, m2, m3;
414 m0 = hp_mem[0];
415 m1 = hp_mem[1];
416 m2 = hp_mem[2];
417 m3 = hp_mem[3];
418 for (i=0;i<len;i++)
419 {
420 opus_val32 x0, x1, tmp0, tmp1, y0, y1;
421 x0 = in[2*i+0];
422 x1 = in[2*i+1];
423 /* First stage */
424 tmp0 = x0-m0;
425 tmp1 = x1-m2;
Jean-Marc Valinb4d0df82016-08-15 19:19:47 -0400426 m0 = coef*x0 + VERY_SMALL + coef2*m0;
427 m2 = coef*x1 + VERY_SMALL + coef2*m2;
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400428 /* Second stage */
429 y0 = tmp0 - m1;
430 y1 = tmp1 - m3;
431 m1 = coef*tmp0 + VERY_SMALL + coef2*m1;
432 m3 = coef*tmp1 + VERY_SMALL + coef2*m3;
433 out[2*i+0] = y0;
434 out[2*i+1] = y1;
435 }
436 hp_mem[0] = m0;
437 hp_mem[1] = m1;
438 hp_mem[2] = m2;
439 hp_mem[3] = m3;
440 } else {
441 float m0, m1;
442 m0 = hp_mem[0];
443 m1 = hp_mem[1];
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500444 for (i=0;i<len;i++)
445 {
446 opus_val32 x, tmp, y;
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400447 x = in[i];
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500448 /* First stage */
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400449 tmp = x-m0;
Jean-Marc Valinb4d0df82016-08-15 19:19:47 -0400450 m0 = coef*x + VERY_SMALL + coef2*m0;
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500451 /* Second stage */
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400452 y = tmp - m1;
453 m1 = coef*tmp + VERY_SMALL + coef2*m1;
454 out[i] = y;
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500455 }
Jean-Marc Valinfb19ba92016-08-15 17:26:20 -0400456 hp_mem[0] = m0;
457 hp_mem[1] = m1;
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500458 }
459}
Jean-Marc Valinac2e6232011-12-29 01:23:33 -0500460#endif
Jean-Marc Valindb13c382011-12-23 11:58:43 -0500461
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400462static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2,
Jean-Marc Valin37d9e132012-07-11 15:53:39 -0400463 int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs)
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400464{
465 int i;
Jean-Marc Valin37d9e132012-07-11 15:53:39 -0400466 int overlap;
467 int inc;
468 inc = 48000/Fs;
469 overlap=overlap48/inc;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400470 g1 = Q15ONE-g1;
471 g2 = Q15ONE-g2;
472 for (i=0;i<overlap;i++)
473 {
474 opus_val32 diff;
475 opus_val16 g, w;
476 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
477 g = SHR32(MAC16_16(MULT16_16(w,g2),
478 Q15ONE-w, g1), 15);
479 diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]));
480 diff = MULT16_16_Q15(g, diff);
481 out[i*channels] = out[i*channels] - diff;
482 out[i*channels+1] = out[i*channels+1] + diff;
483 }
484 for (;i<frame_size;i++)
485 {
486 opus_val32 diff;
487 diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]));
488 diff = MULT16_16_Q15(g2, diff);
489 out[i*channels] = out[i*channels] - diff;
490 out[i*channels+1] = out[i*channels+1] + diff;
491 }
492}
493
Jean-Marc Valinf68799b2012-07-12 17:36:11 -0400494static void gain_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2,
495 int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs)
496{
497 int i;
498 int inc;
499 int overlap;
Jean-Marc Valinca242592012-10-16 00:26:32 -0400500 int c;
Jean-Marc Valinf68799b2012-07-12 17:36:11 -0400501 inc = 48000/Fs;
502 overlap=overlap48/inc;
Jean-Marc Valinca242592012-10-16 00:26:32 -0400503 if (channels==1)
Jean-Marc Valinf68799b2012-07-12 17:36:11 -0400504 {
Jean-Marc Valinca242592012-10-16 00:26:32 -0400505 for (i=0;i<overlap;i++)
506 {
507 opus_val16 g, w;
508 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
509 g = SHR32(MAC16_16(MULT16_16(w,g2),
510 Q15ONE-w, g1), 15);
511 out[i] = MULT16_16_Q15(g, in[i]);
512 }
513 } else {
514 for (i=0;i<overlap;i++)
515 {
516 opus_val16 g, w;
517 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
518 g = SHR32(MAC16_16(MULT16_16(w,g2),
519 Q15ONE-w, g1), 15);
520 out[i*2] = MULT16_16_Q15(g, in[i*2]);
521 out[i*2+1] = MULT16_16_Q15(g, in[i*2+1]);
522 }
Jean-Marc Valinf68799b2012-07-12 17:36:11 -0400523 }
Jean-Marc Valinca242592012-10-16 00:26:32 -0400524 c=0;do {
Jean-Marc Valin4ed7e482013-02-05 01:32:52 -0500525 for (i=overlap;i<frame_size;i++)
Jean-Marc Valinca242592012-10-16 00:26:32 -0400526 {
527 out[i*channels+c] = MULT16_16_Q15(g2, in[i*channels+c]);
528 }
Jean-Marc Valinf68799b2012-07-12 17:36:11 -0400529 }
Jean-Marc Valinca242592012-10-16 00:26:32 -0400530 while (++c<channels);
Jean-Marc Valinf68799b2012-07-12 17:36:11 -0400531}
532
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400533OpusEncoder *opus_encoder_create(opus_int32 Fs, int channels, int application, int *error)
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400534{
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400535 int ret;
Gregory Maxwelle98f1f52011-10-05 01:59:28 -0400536 OpusEncoder *st;
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400537 if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)||
538 (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO
539 && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY))
540 {
541 if (error)
542 *error = OPUS_BAD_ARG;
543 return NULL;
544 }
Gregory Maxwelle98f1f52011-10-05 01:59:28 -0400545 st = (OpusEncoder *)opus_alloc(opus_encoder_get_size(channels));
Jean-Marc Valin85b8e622011-08-29 16:10:08 -0400546 if (st == NULL)
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400547 {
548 if (error)
549 *error = OPUS_ALLOC_FAIL;
550 return NULL;
551 }
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400552 ret = opus_encoder_init(st, Fs, channels, application);
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400553 if (error)
554 *error = ret;
555 if (ret != OPUS_OK)
556 {
Jean-Marc Valin85b8e622011-08-29 16:10:08 -0400557 opus_free(st);
558 st = NULL;
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400559 }
Jean-Marc Valin85b8e622011-08-29 16:10:08 -0400560 return st;
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400561}
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400562
563static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int max_data_bytes)
564{
565 if(!frame_size)frame_size=st->Fs/400;
566 if (st->user_bitrate_bps==OPUS_AUTO)
567 return 60*st->Fs/frame_size + st->Fs*st->channels;
568 else if (st->user_bitrate_bps==OPUS_BITRATE_MAX)
569 return max_data_bytes*8*st->Fs/frame_size;
570 else
571 return st->user_bitrate_bps;
572}
573
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400574#ifndef DISABLE_FLOAT_API
Jean-Marc Valin1ad6f6d2013-10-01 19:25:40 -0400575#ifdef FIXED_POINT
576#define PCM2VAL(x) FLOAT2INT16(x)
577#else
578#define PCM2VAL(x) SCALEIN(x)
579#endif
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400580void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C)
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400581{
582 const float *x;
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400583 opus_val32 scale;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400584 int j;
585 x = (const float *)_x;
586 for (j=0;j<subframe;j++)
Jean-Marc Valin1ad6f6d2013-10-01 19:25:40 -0400587 sub[j] = PCM2VAL(x[(j+offset)*C+c1]);
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400588 if (c2>-1)
589 {
590 for (j=0;j<subframe;j++)
Jean-Marc Valin1ad6f6d2013-10-01 19:25:40 -0400591 sub[j] += PCM2VAL(x[(j+offset)*C+c2]);
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400592 } else if (c2==-2)
593 {
594 int c;
595 for (c=1;c<C;c++)
596 {
597 for (j=0;j<subframe;j++)
Jean-Marc Valin1ad6f6d2013-10-01 19:25:40 -0400598 sub[j] += PCM2VAL(x[(j+offset)*C+c]);
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400599 }
600 }
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400601#ifdef FIXED_POINT
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400602 scale = (1<<SIG_SHIFT);
603#else
604 scale = 1.f;
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400605#endif
Mark Harris3421f6d2016-08-27 07:03:02 -0700606 if (c2==-2)
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400607 scale /= C;
Mark Harris3421f6d2016-08-27 07:03:02 -0700608 else if (c2>-1)
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400609 scale /= 2;
610 for (j=0;j<subframe;j++)
611 sub[j] *= scale;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400612}
613#endif
614
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400615void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C)
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400616{
617 const opus_int16 *x;
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400618 opus_val32 scale;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400619 int j;
620 x = (const opus_int16 *)_x;
621 for (j=0;j<subframe;j++)
622 sub[j] = x[(j+offset)*C+c1];
623 if (c2>-1)
624 {
625 for (j=0;j<subframe;j++)
626 sub[j] += x[(j+offset)*C+c2];
627 } else if (c2==-2)
628 {
629 int c;
630 for (c=1;c<C;c++)
631 {
632 for (j=0;j<subframe;j++)
633 sub[j] += x[(j+offset)*C+c];
634 }
635 }
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400636#ifdef FIXED_POINT
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400637 scale = (1<<SIG_SHIFT);
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400638#else
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400639 scale = 1.f/32768;
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -0400640#endif
Mark Harris3421f6d2016-08-27 07:03:02 -0700641 if (c2==-2)
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400642 scale /= C;
Mark Harris3421f6d2016-08-27 07:03:02 -0700643 else if (c2>-1)
Jean-Marc Valinba7dbb32013-09-09 16:39:19 -0400644 scale /= 2;
645 for (j=0;j<subframe;j++)
646 sub[j] *= scale;
Jean-Marc Valin91904a42013-09-05 21:34:43 -0400647}
648
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500649opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs)
650{
651 int new_size;
652 if (frame_size<Fs/400)
653 return -1;
654 if (variable_duration == OPUS_FRAMESIZE_ARG)
655 new_size = frame_size;
Felicia Lim0962cbe2016-10-27 17:03:36 -0700656 else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_120_MS)
657 {
658 if (variable_duration <= OPUS_FRAMESIZE_40_MS)
659 new_size = (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS);
660 else
661 new_size = (variable_duration-OPUS_FRAMESIZE_2_5_MS-2)*Fs/50;
662 }
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500663 else
664 return -1;
665 if (new_size>frame_size)
666 return -1;
Felicia Lim0962cbe2016-10-27 17:03:36 -0700667 if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs &&
668 50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs &&
669 50*new_size!=4*Fs && 50*new_size!=5*Fs && 50*new_size!=6*Fs)
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500670 return -1;
671 return new_size;
672}
673
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400674opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
675{
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400676 opus_val32 xx, xy, yy;
677 opus_val16 sqrt_xx, sqrt_yy;
678 opus_val16 qrrt_xx, qrrt_yy;
679 int frame_rate;
680 int i;
681 opus_val16 short_alpha;
682
683 frame_rate = Fs/frame_size;
Jean-Marc Valinbe9e7472016-03-21 13:11:48 -0400684 short_alpha = Q15ONE - MULT16_16(25, Q15ONE)/IMAX(50,frame_rate);
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400685 xx=xy=yy=0;
Jean-Marc Valin914476c2016-06-27 23:44:18 -0400686 /* Unroll by 4. The frame size is always a multiple of 4 *except* for
687 2.5 ms frames at 12 kHz. Since this setting is very rare (and very
688 stupid), we just discard the last two samples. */
689 for (i=0;i<frame_size-3;i+=4)
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400690 {
691 opus_val32 pxx=0;
692 opus_val32 pxy=0;
693 opus_val32 pyy=0;
694 opus_val16 x, y;
695 x = pcm[2*i];
696 y = pcm[2*i+1];
697 pxx = SHR32(MULT16_16(x,x),2);
698 pxy = SHR32(MULT16_16(x,y),2);
699 pyy = SHR32(MULT16_16(y,y),2);
700 x = pcm[2*i+2];
701 y = pcm[2*i+3];
702 pxx += SHR32(MULT16_16(x,x),2);
703 pxy += SHR32(MULT16_16(x,y),2);
704 pyy += SHR32(MULT16_16(y,y),2);
705 x = pcm[2*i+4];
706 y = pcm[2*i+5];
707 pxx += SHR32(MULT16_16(x,x),2);
708 pxy += SHR32(MULT16_16(x,y),2);
709 pyy += SHR32(MULT16_16(y,y),2);
710 x = pcm[2*i+6];
711 y = pcm[2*i+7];
712 pxx += SHR32(MULT16_16(x,x),2);
713 pxy += SHR32(MULT16_16(x,y),2);
714 pyy += SHR32(MULT16_16(y,y),2);
715
716 xx += SHR32(pxx, 10);
717 xy += SHR32(pxy, 10);
718 yy += SHR32(pyy, 10);
719 }
720 mem->XX += MULT16_32_Q15(short_alpha, xx-mem->XX);
721 mem->XY += MULT16_32_Q15(short_alpha, xy-mem->XY);
722 mem->YY += MULT16_32_Q15(short_alpha, yy-mem->YY);
723 mem->XX = MAX32(0, mem->XX);
724 mem->XY = MAX32(0, mem->XY);
725 mem->YY = MAX32(0, mem->YY);
726 if (MAX32(mem->XX, mem->YY)>QCONST16(8e-4f, 18))
727 {
Jean-Marc Valin9b1a27a2016-06-29 23:11:57 -0400728 opus_val16 corr;
729 opus_val16 ldiff;
730 opus_val16 width;
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400731 sqrt_xx = celt_sqrt(mem->XX);
732 sqrt_yy = celt_sqrt(mem->YY);
733 qrrt_xx = celt_sqrt(sqrt_xx);
734 qrrt_yy = celt_sqrt(sqrt_yy);
735 /* Inter-channel correlation */
736 mem->XY = MIN32(mem->XY, sqrt_xx*sqrt_yy);
737 corr = SHR32(frac_div32(mem->XY,EPSILON+MULT16_16(sqrt_xx,sqrt_yy)),16);
738 /* Approximate loudness difference */
Jean-Marc Valinbe9e7472016-03-21 13:11:48 -0400739 ldiff = MULT16_16(Q15ONE, ABS16(qrrt_xx-qrrt_yy))/(EPSILON+qrrt_xx+qrrt_yy);
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400740 width = MULT16_16_Q15(celt_sqrt(QCONST32(1.f,30)-MULT16_16(corr,corr)), ldiff);
741 /* Smoothing over one second */
742 mem->smoothed_width += (width-mem->smoothed_width)/frame_rate;
743 /* Peak follower */
744 mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width);
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400745 }
746 /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/
Jean-Marc Valinbe9e7472016-03-21 13:11:48 -0400747 return EXTRACT16(MIN32(Q15ONE, MULT16_16(20, mem->max_follower)));
Jean-Marc Valind865fe62013-03-11 11:35:10 -0400748}
749
Jean-Marc Valin2b011b62016-06-21 12:38:25 -0400750static int decide_fec(int useInBandFEC, int PacketLoss_perc, int last_fec, int mode, int *bandwidth, opus_int32 rate)
751{
752 int orig_bandwidth;
753 if (!useInBandFEC || PacketLoss_perc == 0 || mode == MODE_CELT_ONLY)
754 return 0;
755 orig_bandwidth = *bandwidth;
756 for (;;)
757 {
758 opus_int32 hysteresis;
759 opus_int32 LBRR_rate_thres_bps;
760 /* Compute threshold for using FEC at the current bandwidth setting */
761 LBRR_rate_thres_bps = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND)];
762 hysteresis = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND) + 1];
763 if (last_fec == 1) LBRR_rate_thres_bps -= hysteresis;
764 if (last_fec == 0) LBRR_rate_thres_bps += hysteresis;
765 LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps,
766 125 - silk_min( PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
767 /* If loss <= 5%, we look at whether we have enough rate to enable FEC.
768 If loss > 5%, we decrease the bandwidth until we can enable FEC. */
769 if (rate > LBRR_rate_thres_bps)
770 return 1;
771 else if (PacketLoss_perc <= 5)
772 return 0;
773 else if (*bandwidth > OPUS_BANDWIDTH_NARROWBAND)
774 (*bandwidth)--;
775 else
776 break;
777 }
778 /* Couldn't find any bandwidth to enable FEC, keep original bandwidth. */
779 *bandwidth = orig_bandwidth;
780 return 0;
781}
782
Jean-Marc Valinb3c9e792016-06-21 13:37:29 -0400783static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr, int fec) {
Jean-Marc Valin66f3ef32015-12-24 13:03:28 -0500784 int entry;
785 int i;
786 int N;
787 int silk_rate;
788 static int rate_table[][5] = {
789 /* |total| |-------- SILK------------|
Jean-Marc Valinb3c9e792016-06-21 13:37:29 -0400790 |-- No FEC -| |--- FEC ---|
791 10ms 20ms 10ms 20ms */
Jean-Marc Valin66f3ef32015-12-24 13:03:28 -0500792 { 0, 0, 0, 0, 0},
Jean-Marc Valinb3c9e792016-06-21 13:37:29 -0400793 {12000, 10000, 10000, 11000, 11000},
794 {16000, 13500, 13500, 15000, 15000},
795 {20000, 16000, 16000, 18000, 18000},
796 {24000, 18000, 18000, 21000, 21000},
797 {32000, 22000, 22000, 28000, 28000},
798 {64000, 38000, 38000, 50000, 50000}
Jean-Marc Valin66f3ef32015-12-24 13:03:28 -0500799 };
Jean-Marc Valinb3c9e792016-06-21 13:37:29 -0400800 entry = 1 + frame20ms + 2*fec;
Jean-Marc Valin66f3ef32015-12-24 13:03:28 -0500801 N = sizeof(rate_table)/sizeof(rate_table[0]);
802 for (i=1;i<N;i++)
803 {
804 if (rate_table[i][0] > rate) break;
805 }
806 if (i == N)
807 {
808 silk_rate = rate_table[i-1][entry];
809 /* For now, just give 50% of the extra bits to SILK. */
810 silk_rate += (rate-rate_table[i-1][0])/2;
811 } else {
812 opus_int32 lo, hi, x0, x1;
813 lo = rate_table[i-1][entry];
814 hi = rate_table[i][entry];
815 x0 = rate_table[i-1][0];
816 x1 = rate_table[i][0];
817 silk_rate = (lo*(x1-rate) + hi*(rate-x0))/(x1-x0);
818 }
819 if (!vbr)
820 {
Jean-Marc Valine7758962016-06-02 18:11:33 -0400821 /* Tiny boost to SILK for CBR. We should probably tune this better. */
822 silk_rate += 100;
Jean-Marc Valin66f3ef32015-12-24 13:03:28 -0500823 }
Jean-Marc Valinb3c9e792016-06-21 13:37:29 -0400824 if (bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND)
825 silk_rate += 300;
Jean-Marc Valin66f3ef32015-12-24 13:03:28 -0500826 return silk_rate;
827}
828
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400829/* Returns the equivalent bitrate corresponding to 20 ms frames,
830 complexity 10 VBR operation. */
831static opus_int32 compute_equiv_rate(opus_int32 bitrate, int channels,
Jean-Marc Valin099fc052016-06-20 18:54:06 -0400832 int frame_rate, int vbr, int mode, int complexity, int loss)
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400833{
Jean-Marc Valin099fc052016-06-20 18:54:06 -0400834 opus_int32 equiv;
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400835 equiv = bitrate;
836 /* Take into account overhead from smaller frames. */
837 equiv -= (40*channels+20)*(frame_rate - 50);
Jean-Marc Valin508c5712016-06-02 19:08:01 -0400838 /* CBR is about a 8% penalty for both SILK and CELT. */
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400839 if (!vbr)
Jean-Marc Valinbe5a7da2016-06-02 18:15:00 -0400840 equiv -= equiv/12;
Jean-Marc Valin508c5712016-06-02 19:08:01 -0400841 /* Complexity makes about 10% difference (from 0 to 10) in general. */
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400842 equiv = equiv * (90+complexity)/100;
843 if (mode == MODE_SILK_ONLY || mode == MODE_HYBRID)
844 {
Jean-Marc Valinbe5a7da2016-06-02 18:15:00 -0400845 /* SILK complexity 0-1 uses the non-delayed-decision NSQ, which
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400846 costs about 20%. */
Jean-Marc Valinbe5a7da2016-06-02 18:15:00 -0400847 if (complexity<2)
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400848 equiv = equiv*4/5;
Jean-Marc Valin099fc052016-06-20 18:54:06 -0400849 equiv -= equiv*loss/(6*loss + 10);
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400850 } else if (mode == MODE_CELT_ONLY) {
851 /* CELT complexity 0-4 doesn't have the pitch filter, which costs
852 about 10%. */
853 if (complexity<5)
854 equiv = equiv*9/10;
855 } else {
856 /* Mode not known yet */
Jean-Marc Valin099fc052016-06-20 18:54:06 -0400857 /* Half the SILK loss*/
858 equiv -= equiv*loss/(12*loss + 20);
Jean-Marc Valin45773d82016-04-27 04:04:50 -0400859 }
860 return equiv;
861}
862
Felicia Lim425e8a92016-05-16 15:11:10 +0200863#ifndef DISABLE_FLOAT_API
864
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400865static int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth)
Felicia Lim425e8a92016-05-16 15:11:10 +0200866{
867 int silence = 0;
868 opus_val32 sample_max = 0;
869
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400870 sample_max = celt_maxabs16(pcm, frame_size*channels);
Felicia Lim425e8a92016-05-16 15:11:10 +0200871
872#ifdef FIXED_POINT
873 silence = (sample_max == 0);
Mark Harris43b47a42016-07-21 22:05:21 -0700874 (void)lsb_depth;
Felicia Lim425e8a92016-05-16 15:11:10 +0200875#else
876 silence = (sample_max <= (opus_val16) 1 / (1 << lsb_depth));
877#endif
878
879 return silence;
880}
881
Jean-Marc Valinadf94f22016-08-15 18:24:30 -0400882#ifdef FIXED_POINT
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400883static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
Felicia Lim33f18a22016-05-16 15:52:44 +0200884{
885 int i;
Felicia Lim33f18a22016-05-16 15:52:44 +0200886 opus_val32 sample_max;
887 int max_shift;
888 int shift;
Felicia Lim33f18a22016-05-16 15:52:44 +0200889 opus_val32 energy = 0;
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400890 int len = frame_size*channels;
Jean-Marc Valinadf94f22016-08-15 18:24:30 -0400891 (void)arch;
Felicia Lim33f18a22016-05-16 15:52:44 +0200892 /* Max amplitude in the signal */
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400893 sample_max = celt_maxabs16(pcm, len);
Felicia Lim33f18a22016-05-16 15:52:44 +0200894
895 /* Compute the right shift required in the MAC to avoid an overflow */
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400896 max_shift = celt_ilog2(len);
Felicia Lim33f18a22016-05-16 15:52:44 +0200897 shift = IMAX(0, (celt_ilog2(sample_max) << 1) + max_shift - 28);
Felicia Lim33f18a22016-05-16 15:52:44 +0200898
899 /* Compute the energy */
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400900 for (i=0; i<len; i++)
Felicia Lim33f18a22016-05-16 15:52:44 +0200901 energy += SHR32(MULT16_16(pcm[i], pcm[i]), shift);
902
903 /* Normalize energy by the frame size and left-shift back to the original position */
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400904 energy /= len;
Felicia Lim33f18a22016-05-16 15:52:44 +0200905 energy = SHL32(energy, shift);
906
907 return energy;
908}
Jean-Marc Valinadf94f22016-08-15 18:24:30 -0400909#else
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400910static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
Jean-Marc Valinadf94f22016-08-15 18:24:30 -0400911{
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400912 int len = frame_size*channels;
913 return celt_inner_prod(pcm, pcm, len, arch)/len;
Jean-Marc Valinadf94f22016-08-15 18:24:30 -0400914}
915#endif
Felicia Lim33f18a22016-05-16 15:52:44 +0200916
Felicia Lim36481342016-05-16 15:29:53 +0200917/* Decides if DTX should be turned on (=1) or off (=0) */
918static int decide_dtx_mode(float activity_probability, /* probability that current frame contains speech/music */
919 int *nb_no_activity_frames, /* number of consecutive frames with no activity */
Felicia Lim33f18a22016-05-16 15:52:44 +0200920 opus_val32 peak_signal_energy, /* peak energy of desired signal detected so far */
921 const opus_val16 *pcm, /* input pcm signal */
922 int frame_size, /* frame size */
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400923 int channels,
Jean-Marc Valinadf94f22016-08-15 18:24:30 -0400924 int is_silence, /* only digital silence detected in this frame */
925 int arch
Felicia Lim36481342016-05-16 15:29:53 +0200926 )
927{
Felicia Lim33f18a22016-05-16 15:52:44 +0200928 int is_noise;
929 opus_val32 noise_energy;
930 int is_sufficiently_quiet;
Felicia Lim36481342016-05-16 15:29:53 +0200931
932 if (!is_silence)
933 {
934 is_noise = activity_probability < DTX_ACTIVITY_THRESHOLD;
Felicia Lim33f18a22016-05-16 15:52:44 +0200935 if (is_noise)
936 {
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -0400937 noise_energy = compute_frame_energy(pcm, frame_size, channels, arch);
Felicia Lim33f18a22016-05-16 15:52:44 +0200938 is_sufficiently_quiet = peak_signal_energy >= (PSEUDO_SNR_THRESHOLD * noise_energy);
939 }
Felicia Lim36481342016-05-16 15:29:53 +0200940 }
941
Felicia Lim33f18a22016-05-16 15:52:44 +0200942 if (is_silence || (is_noise && is_sufficiently_quiet))
Felicia Lim36481342016-05-16 15:29:53 +0200943 {
944 /* The number of consecutive DTX frames should be within the allowed bounds */
945 (*nb_no_activity_frames)++;
946
947 if (*nb_no_activity_frames > NB_SPEECH_FRAMES_BEFORE_DTX)
948 {
949 if (*nb_no_activity_frames <= (NB_SPEECH_FRAMES_BEFORE_DTX + MAX_CONSECUTIVE_DTX))
950 /* Valid frame for DTX! */
951 return 1;
952 else
953 (*nb_no_activity_frames) = NB_SPEECH_FRAMES_BEFORE_DTX;
954 }
955 } else
956 (*nb_no_activity_frames) = 0;
957
958 return 0;
959}
960
Felicia Lim425e8a92016-05-16 15:11:10 +0200961#endif
962
Felicia Lim8bca1542016-09-22 11:06:11 +0200963static opus_int32 encode_multiframe_packet(OpusEncoder *st,
964 const opus_val16 *pcm,
965 int nb_frames,
966 int frame_size,
967 unsigned char *data,
968 opus_int32 out_data_bytes,
969 int to_celt,
970 int lsb_depth,
971 int float_api)
972{
973 int i;
974 int ret = 0;
975 VARDECL(unsigned char, tmp_data);
976 int bak_mode, bak_bandwidth, bak_channels, bak_to_mono;
977 VARDECL(OpusRepacketizer, rp);
Felicia Lim0962cbe2016-10-27 17:03:36 -0700978 int max_header_bytes;
Felicia Lim8bca1542016-09-22 11:06:11 +0200979 opus_int32 bytes_per_frame;
980 opus_int32 cbr_bytes;
981 opus_int32 repacketize_len;
982 int tmp_len;
983 ALLOC_STACK;
984
Felicia Lim0962cbe2016-10-27 17:03:36 -0700985 /* Worst cases:
986 * 2 frames: Code 2 with different compressed sizes
987 * >2 frames: Code 3 VBR */
988 max_header_bytes = nb_frames == 2 ? 3 : (2+(nb_frames-1)*2);
Felicia Lim8bca1542016-09-22 11:06:11 +0200989
Felicia Lim0962cbe2016-10-27 17:03:36 -0700990 if (st->use_vbr || st->user_bitrate_bps==OPUS_BITRATE_MAX)
991 repacketize_len = out_data_bytes;
992 else {
993 cbr_bytes = 3*st->bitrate_bps/(3*8*st->Fs/(frame_size*nb_frames));
994 repacketize_len = IMIN(cbr_bytes, out_data_bytes);
995 }
996 bytes_per_frame = IMIN(1276, 1+(repacketize_len-max_header_bytes)/nb_frames);
997
998 ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char);
Felicia Lim8bca1542016-09-22 11:06:11 +0200999 ALLOC(rp, 1, OpusRepacketizer);
1000 opus_repacketizer_init(rp);
1001
1002 bak_mode = st->user_forced_mode;
1003 bak_bandwidth = st->user_bandwidth;
1004 bak_channels = st->force_channels;
1005
1006 st->user_forced_mode = st->mode;
1007 st->user_bandwidth = st->bandwidth;
1008 st->force_channels = st->stream_channels;
Felicia Lim8bca1542016-09-22 11:06:11 +02001009
Felicia Lim0962cbe2016-10-27 17:03:36 -07001010 bak_to_mono = st->silk_mode.toMono;
Felicia Lim8bca1542016-09-22 11:06:11 +02001011 if (bak_to_mono)
1012 st->force_channels = 1;
1013 else
1014 st->prev_channels = st->stream_channels;
1015
1016 for (i=0;i<nb_frames;i++)
1017 {
1018 st->silk_mode.toMono = 0;
Felicia Lim0962cbe2016-10-27 17:03:36 -07001019 st->nonfinal_frame = i<(nb_frames-1);
Felicia Lim8bca1542016-09-22 11:06:11 +02001020
1021 /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */
1022 if (to_celt && i==nb_frames-1)
1023 st->user_forced_mode = MODE_CELT_ONLY;
1024
1025 tmp_len = opus_encode_native(st, pcm+i*(st->channels*frame_size), frame_size,
1026 tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth, NULL, 0, 0, 0, 0,
1027 NULL, float_api);
1028
1029 if (tmp_len<0)
1030 {
1031 RESTORE_STACK;
1032 return OPUS_INTERNAL_ERROR;
1033 }
1034
1035 ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len);
1036
1037 if (ret<0)
1038 {
1039 RESTORE_STACK;
1040 return OPUS_INTERNAL_ERROR;
1041 }
1042 }
1043
Felicia Lim8bca1542016-09-22 11:06:11 +02001044 ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr);
1045
1046 if (ret<0)
1047 {
1048 RESTORE_STACK;
1049 return OPUS_INTERNAL_ERROR;
1050 }
1051
1052 /* Discard configs that were forced locally for the purpose of repacketization */
1053 st->user_forced_mode = bak_mode;
1054 st->user_bandwidth = bak_bandwidth;
1055 st->force_channels = bak_channels;
1056 st->silk_mode.toMono = bak_to_mono;
1057
1058 RESTORE_STACK;
1059 return ret;
1060}
1061
Jean-Marc Valinb3eba242012-12-20 23:11:53 -05001062opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001063 unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001064 const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
1065 int analysis_channels, downmix_func downmix, int float_api)
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04001066{
Ralph Giles641eea82011-08-02 10:06:59 -07001067 void *silk_enc;
1068 CELTEncoder *celt_enc;
Jean-Marc Valine2d1ef12010-07-06 15:39:19 -04001069 int i;
Ralph Giles641eea82011-08-02 10:06:59 -07001070 int ret=0;
Jean-Marc Valin59354a72012-03-08 12:19:07 -05001071 opus_int32 nBytes;
Ralph Giles641eea82011-08-02 10:06:59 -07001072 ec_enc enc;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001073 int bytes_target;
Jean-Marc Valine3de5052011-02-20 12:23:48 -05001074 int prefill=0;
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001075 int start_band = 0;
Jean-Marc Valine2a09db2011-03-02 17:54:43 -05001076 int redundancy = 0;
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001077 int redundancy_bytes = 0; /* Number of bytes to use for redundancy frame */
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001078 int celt_to_silk = 0;
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001079 VARDECL(opus_val16, pcm_buf);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001080 int nb_compr_bytes;
1081 int to_celt = 0;
Jean-Marc Valin06cee2b2011-08-19 16:11:41 -04001082 opus_uint32 redundant_rng = 0;
Jean-Marc Valin957f7f12011-09-01 18:02:43 -04001083 int cutoff_Hz, hp_freq_smth1;
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001084 int voice_est; /* Probability of voice in Q7 */
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001085 opus_int32 equiv_rate;
Jean-Marc Valind186c912011-09-08 15:13:46 -04001086 int delay_compensation;
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001087 int frame_rate;
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001088 opus_int32 max_rate; /* Max bitrate we're allowed to use */
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001089 int curr_bandwidth;
Jean-Marc Valinf68799b2012-07-12 17:36:11 -04001090 opus_val16 HB_gain;
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001091 opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */
Jean-Marc Valinbb43b8b2012-12-17 18:02:56 -05001092 int total_buffer;
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001093 opus_val16 stereo_width;
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001094 const CELTMode *celt_mode;
Timothy B. Terriberry23f503a2014-12-26 08:31:39 -08001095#ifndef DISABLE_FLOAT_API
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001096 AnalysisInfo analysis_info;
Jean-Marc Valin29254442013-09-28 19:29:23 -04001097 int analysis_read_pos_bak=-1;
1098 int analysis_read_subframe_bak=-1;
Felicia Lim425e8a92016-05-16 15:11:10 +02001099 int is_silence = 0;
Timothy B. Terriberry23f503a2014-12-26 08:31:39 -08001100#endif
Jean-Marc Valine22cc272011-10-14 13:48:17 -04001101 VARDECL(opus_val16, tmp_prefill);
1102
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001103 ALLOC_STACK;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001104
Gregory Maxwelle7028172011-11-19 23:58:09 -05001105 max_data_bytes = IMIN(1276, out_data_bytes);
Jean-Marc Valin904e7a82011-09-11 14:29:46 -04001106
Jean-Marc Valin2b98bdf2011-08-20 00:21:46 -04001107 st->rangeFinal = 0;
Mark Harrisd73c5a92016-11-05 22:01:52 -07001108 if (frame_size <= 0 || max_data_bytes <= 0)
Jean-Marc Valin5609cec2011-12-13 14:52:43 -05001109 {
1110 RESTORE_STACK;
1111 return OPUS_BAD_ARG;
1112 }
Felicia Lim9962bf32016-10-27 17:00:05 -07001113
1114 /* Cannot encode 100 ms in 1 byte */
1115 if (max_data_bytes==1 && st->Fs==(frame_size*10))
1116 {
1117 RESTORE_STACK;
1118 return OPUS_BUFFER_TOO_SMALL;
1119 }
1120
Jean-Marc Valin5095c472011-05-05 19:47:48 -04001121 silk_enc = (char*)st+st->silk_enc_offset;
1122 celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -04001123 if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
Jean-Marc Valind186c912011-09-08 15:13:46 -04001124 delay_compensation = 0;
1125 else
1126 delay_compensation = st->delay_compensation;
Jean-Marc Valinba547462011-05-10 17:54:41 -04001127
1128 lsb_depth = IMIN(lsb_depth, st->lsb_depth);
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001129
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001130 celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -04001131#ifndef DISABLE_FLOAT_API
Timothy B. Terriberry23f503a2014-12-26 08:31:39 -08001132 analysis_info.valid = 0;
Jean-Marc Valinf5645f52013-09-16 14:36:53 -04001133#ifdef FIXED_POINT
Jean-Marc Valin29254442013-09-28 19:29:23 -04001134 if (st->silk_mode.complexity >= 10 && st->Fs==48000)
Jean-Marc Valinf5645f52013-09-16 14:36:53 -04001135#else
Jean-Marc Valin29254442013-09-28 19:29:23 -04001136 if (st->silk_mode.complexity >= 7 && st->Fs==48000)
Jean-Marc Valinf5645f52013-09-16 14:36:53 -04001137#endif
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001138 {
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -04001139 if (is_digital_silence(pcm, frame_size, st->channels, lsb_depth))
Felicia Lim425e8a92016-05-16 15:11:10 +02001140 {
1141 is_silence = 1;
1142 } else {
1143 analysis_read_pos_bak = st->analysis.read_pos;
1144 analysis_read_subframe_bak = st->analysis.read_subframe;
1145 run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size,
1146 c1, c2, analysis_channels, st->Fs,
1147 lsb_depth, downmix, &analysis_info);
1148 }
Felicia Lim33f18a22016-05-16 15:52:44 +02001149
1150 /* Track the peak signal energy */
1151 if (!is_silence && analysis_info.activity_probability > DTX_ACTIVITY_THRESHOLD)
Jean-Marc Valinadf94f22016-08-15 18:24:30 -04001152 st->peak_signal_energy = MAX32(MULT16_32_Q15(QCONST16(0.999, 15), st->peak_signal_energy),
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -04001153 compute_frame_energy(pcm, frame_size, st->channels, st->arch));
Jean-Marc Valina4c25122013-09-28 17:22:41 -04001154 }
Timothy B. Terriberry23f503a2014-12-26 08:31:39 -08001155#else
1156 (void)analysis_pcm;
1157 (void)analysis_size;
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001158#endif
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001159
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -04001160#ifndef DISABLE_FLOAT_API
Felicia Lim425e8a92016-05-16 15:11:10 +02001161 /* Reset voice_ratio if this frame is not silent or if analysis is disabled.
1162 * Otherwise, preserve voice_ratio from the last non-silent frame */
1163 if (!is_silence)
1164 st->voice_ratio = -1;
1165
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001166 st->detected_bandwidth = 0;
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001167 if (analysis_info.valid)
Jean-Marc Valin1a2e7652011-11-06 23:27:16 -05001168 {
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001169 int analysis_bandwidth;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001170 if (st->signal_type == OPUS_AUTO)
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001171 st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob));
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001172
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001173 analysis_bandwidth = analysis_info.bandwidth;
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001174 if (analysis_bandwidth<=12)
1175 st->detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
1176 else if (analysis_bandwidth<=14)
1177 st->detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
1178 else if (analysis_bandwidth<=16)
1179 st->detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
1180 else if (analysis_bandwidth<=18)
1181 st->detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
1182 else
1183 st->detected_bandwidth = OPUS_BANDWIDTH_FULLBAND;
Jean-Marc Valin1a2e7652011-11-06 23:27:16 -05001184 }
Felicia Lim425e8a92016-05-16 15:11:10 +02001185#else
1186 st->voice_ratio = -1;
Jean-Marc Valin862e1822010-07-20 12:19:00 -04001187#endif
Jean-Marc Valin7ebacf42012-11-13 02:24:07 -05001188
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001189 if (st->channels==2 && st->force_channels!=1)
1190 stereo_width = compute_stereo_width(pcm, frame_size, st->Fs, &st->width_mem);
1191 else
1192 stereo_width = 0;
Jean-Marc Valin7ebacf42012-11-13 02:24:07 -05001193 total_buffer = delay_compensation;
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001194 st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001195
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001196 frame_rate = st->Fs/frame_size;
Jean-Marc Valineff72e42016-07-07 02:33:58 -04001197 if (!st->use_vbr)
1198 {
1199 int cbrBytes;
Felicia Lime564cc52016-10-28 09:34:51 -07001200 /* Multiply by 12 to make sure the division is exact. */
1201 int frame_rate12 = 12*st->Fs/frame_size;
Jean-Marc Valinbcea2332016-07-07 11:54:10 -04001202 /* We need to make sure that "int" values always fit in 16 bits. */
Felicia Lime564cc52016-10-28 09:34:51 -07001203 cbrBytes = IMIN( (12*st->bitrate_bps/8 + frame_rate12/2)/frame_rate12, max_data_bytes);
1204 st->bitrate_bps = cbrBytes*(opus_int32)frame_rate12*8/12;
Jean-Marc Valin70e3c342016-09-09 16:51:01 -04001205 /* Make sure we provide at least one byte to avoid failing. */
1206 max_data_bytes = IMAX(1, cbrBytes);
Jean-Marc Valineff72e42016-07-07 02:33:58 -04001207 }
Jean-Marc Valin5609cec2011-12-13 14:52:43 -05001208 if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8
1209 || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400)))
1210 {
Gregory Maxwell31e8a842012-07-18 10:06:01 -04001211 /*If the space is too low to do something useful, emit 'PLC' frames.*/
Jean-Marc Valin5609cec2011-12-13 14:52:43 -05001212 int tocmode = st->mode;
Gregory Maxwell31e8a842012-07-18 10:06:01 -04001213 int bw = st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth;
Felicia Lim9962bf32016-10-27 17:00:05 -07001214 int packet_code = 0;
1215 int num_multiframes = 0;
1216
Jean-Marc Valin5609cec2011-12-13 14:52:43 -05001217 if (tocmode==0)
1218 tocmode = MODE_SILK_ONLY;
1219 if (frame_rate>100)
1220 tocmode = MODE_CELT_ONLY;
Felicia Lim9962bf32016-10-27 17:00:05 -07001221 /* 40 ms -> 2 x 20 ms if in CELT_ONLY or HYBRID mode */
1222 if (frame_rate==25 && tocmode!=MODE_SILK_ONLY)
1223 {
1224 frame_rate = 50;
1225 packet_code = 1;
1226 }
1227
1228 /* >= 60 ms frames */
1229 if (frame_rate<=16)
1230 {
1231 /* 1 x 60 ms, 2 x 40 ms, 2 x 60 ms */
1232 if (out_data_bytes==1 || (tocmode==MODE_SILK_ONLY && frame_rate!=10))
1233 {
1234 tocmode = MODE_SILK_ONLY;
1235
1236 packet_code = frame_rate <= 12;
1237 frame_rate = frame_rate == 12 ? 25 : 16;
1238 }
1239 else
1240 {
1241 num_multiframes = 50/frame_rate;
1242 frame_rate = 50;
1243 packet_code = 3;
1244 }
1245 }
1246
Gregory Maxwell31e8a842012-07-18 10:06:01 -04001247 if(tocmode==MODE_SILK_ONLY&&bw>OPUS_BANDWIDTH_WIDEBAND)
1248 bw=OPUS_BANDWIDTH_WIDEBAND;
1249 else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND)
1250 bw=OPUS_BANDWIDTH_NARROWBAND;
Jean-Marc Valine959f0d2016-07-07 01:23:11 -04001251 else if (tocmode==MODE_HYBRID&&bw<=OPUS_BANDWIDTH_SUPERWIDEBAND)
Gregory Maxwell31e8a842012-07-18 10:06:01 -04001252 bw=OPUS_BANDWIDTH_SUPERWIDEBAND;
Felicia Lim9962bf32016-10-27 17:00:05 -07001253
Gregory Maxwell31e8a842012-07-18 10:06:01 -04001254 data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels);
Felicia Lim9962bf32016-10-27 17:00:05 -07001255 data[0] |= packet_code;
1256
1257 ret = packet_code <= 1 ? 1 : 2;
1258
1259 max_data_bytes = IMAX(max_data_bytes, ret);
1260
1261 if (packet_code==3)
1262 data[1] = num_multiframes;
1263
Jean-Marc Valineff72e42016-07-07 02:33:58 -04001264 if (!st->use_vbr)
1265 {
1266 ret = opus_packet_pad(data, ret, max_data_bytes);
1267 if (ret == OPUS_OK)
1268 ret = max_data_bytes;
Jean-Marc Valin70e3c342016-09-09 16:51:01 -04001269 else
1270 ret = OPUS_INTERNAL_ERROR;
Jean-Marc Valineff72e42016-07-07 02:33:58 -04001271 }
Jean-Marc Valin5609cec2011-12-13 14:52:43 -05001272 RESTORE_STACK;
Jean-Marc Valineff72e42016-07-07 02:33:58 -04001273 return ret;
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001274 }
Koen Vos43a0de42011-10-24 09:10:58 -04001275 max_rate = frame_rate*max_data_bytes*8;
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001276
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001277 /* Equivalent 20-ms rate for mode/channel/bandwidth decisions */
Jean-Marc Valin45773d82016-04-27 04:04:50 -04001278 equiv_rate = compute_equiv_rate(st->bitrate_bps, st->channels, st->Fs/frame_size,
Jean-Marc Valin099fc052016-06-20 18:54:06 -04001279 st->use_vbr, 0, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001280
1281 if (st->signal_type == OPUS_SIGNAL_VOICE)
1282 voice_est = 127;
1283 else if (st->signal_type == OPUS_SIGNAL_MUSIC)
1284 voice_est = 0;
1285 else if (st->voice_ratio >= 0)
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001286 {
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001287 voice_est = st->voice_ratio*327>>8;
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001288 /* For AUDIO, never be more than 90% confident of having speech */
1289 if (st->application == OPUS_APPLICATION_AUDIO)
1290 voice_est = IMIN(voice_est, 115);
1291 } else if (st->application == OPUS_APPLICATION_VOIP)
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001292 voice_est = 115;
1293 else
Jean-Marc Valin9dc0e402011-10-24 20:26:29 -04001294 voice_est = 48;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001295
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001296 if (st->force_channels!=OPUS_AUTO && st->channels == 2)
Koen Vos479e18b2011-05-25 23:09:52 -04001297 {
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001298 st->stream_channels = st->force_channels;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001299 } else {
Jean-Marc Valin1e22a4b2011-10-07 22:29:38 -04001300#ifdef FUZZING
1301 /* Random mono/stereo decision */
1302 if (st->channels == 2 && (rand()&0x1F)==0)
1303 st->stream_channels = 3-st->stream_channels;
1304#else
1305 /* Rate-dependent mono-stereo decision */
1306 if (st->channels == 2)
1307 {
1308 opus_int32 stereo_threshold;
1309 stereo_threshold = stereo_music_threshold + ((voice_est*voice_est*(stereo_voice_threshold-stereo_music_threshold))>>14);
1310 if (st->stream_channels == 2)
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001311 stereo_threshold -= 1000;
Jean-Marc Valin1e22a4b2011-10-07 22:29:38 -04001312 else
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001313 stereo_threshold += 1000;
Jean-Marc Valin1e22a4b2011-10-07 22:29:38 -04001314 st->stream_channels = (equiv_rate > stereo_threshold) ? 2 : 1;
1315 } else {
1316 st->stream_channels = st->channels;
1317 }
Jean-Marc Valinf334c822011-08-11 16:21:58 -04001318#endif
Jean-Marc Valin1e22a4b2011-10-07 22:29:38 -04001319 }
Jean-Marc Valin45773d82016-04-27 04:04:50 -04001320 /* Update equivalent rate for channels decision. */
1321 equiv_rate = compute_equiv_rate(st->bitrate_bps, st->stream_channels, st->Fs/frame_size,
Jean-Marc Valin099fc052016-06-20 18:54:06 -04001322 st->use_vbr, 0, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
Jean-Marc Valinf334c822011-08-11 16:21:58 -04001323
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04001324 /* Mode selection depending on application and signal type */
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -04001325 if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
Jean-Marc Valind186c912011-09-08 15:13:46 -04001326 {
1327 st->mode = MODE_CELT_ONLY;
1328 } else if (st->user_forced_mode == OPUS_AUTO)
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001329 {
Jean-Marc Valin9fd13d62011-10-07 22:50:49 -04001330#ifdef FUZZING
1331 /* Random mode switching */
1332 if ((rand()&0xF)==0)
1333 {
1334 if ((rand()&0x1)==0)
1335 st->mode = MODE_CELT_ONLY;
1336 else
1337 st->mode = MODE_SILK_ONLY;
1338 } else {
1339 if (st->prev_mode==MODE_CELT_ONLY)
1340 st->mode = MODE_CELT_ONLY;
1341 else
1342 st->mode = MODE_SILK_ONLY;
1343 }
1344#else
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001345 opus_int32 mode_voice, mode_music;
1346 opus_int32 threshold;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001347
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001348 /* Interpolate based on stereo width */
Jean-Marc Valin16ba19a2013-06-27 03:40:44 -04001349 mode_voice = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[0][0])
1350 + MULT16_32_Q15(stereo_width,mode_thresholds[1][0]));
1351 mode_music = (opus_int32)(MULT16_32_Q15(Q15ONE-stereo_width,mode_thresholds[1][1])
1352 + MULT16_32_Q15(stereo_width,mode_thresholds[1][1]));
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001353 /* Interpolate based on speech/music probability */
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001354 threshold = mode_music + ((voice_est*voice_est*(mode_voice-mode_music))>>14);
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001355 /* Bias towards SILK for VoIP because of some useful features */
1356 if (st->application == OPUS_APPLICATION_VOIP)
1357 threshold += 8000;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04001358
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001359 /*printf("%f %d\n", stereo_width/(float)Q15ONE, threshold);*/
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001360 /* Hysteresis */
1361 if (st->prev_mode == MODE_CELT_ONLY)
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001362 threshold -= 4000;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001363 else if (st->prev_mode>0)
Jean-Marc Valind865fe62013-03-11 11:35:10 -04001364 threshold += 4000;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04001365
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001366 st->mode = (equiv_rate >= threshold) ? MODE_CELT_ONLY: MODE_SILK_ONLY;
Jean-Marc Valin9dc0e402011-10-24 20:26:29 -04001367
Jean-Marc Valin6ef37872011-10-27 13:39:12 -04001368 /* When FEC is enabled and there's enough packet loss, use SILK */
Jean-Marc Valin9dc0e402011-10-24 20:26:29 -04001369 if (st->silk_mode.useInBandFEC && st->silk_mode.packetLossPercentage > (128-voice_est)>>4)
1370 st->mode = MODE_SILK_ONLY;
Felicia Lim36481342016-05-16 15:29:53 +02001371 /* When encoding voice and DTX is enabled but the generalized DTX cannot be used,
Felicia Lime1bce7b2016-07-20 13:37:13 +02001372 because of complexity and sampling frequency settings, switch to SILK DTX and
1373 set the encoder to SILK mode */
1374#ifndef DISABLE_FLOAT_API
Felicia Lim36481342016-05-16 15:29:53 +02001375 st->silk_mode.useDTX = st->use_dtx && !(analysis_info.valid || is_silence);
Felicia Lime1bce7b2016-07-20 13:37:13 +02001376#else
1377 st->silk_mode.useDTX = st->use_dtx;
1378#endif
Jean-Marc Valin6ef37872011-10-27 13:39:12 -04001379 if (st->silk_mode.useDTX && voice_est > 100)
1380 st->mode = MODE_SILK_ONLY;
Jean-Marc Valin9fd13d62011-10-07 22:50:49 -04001381#endif
Felicia Lim0962cbe2016-10-27 17:03:36 -07001382
1383 /* If max_data_bytes represents less than 6 kb/s, switch to CELT-only mode */
1384 if (max_data_bytes < (frame_rate > 50 ? 9000 : 6000)*frame_size / (st->Fs * 8))
1385 st->mode = MODE_CELT_ONLY;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001386 } else {
1387 st->mode = st->user_forced_mode;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04001388 }
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001389
Jean-Marc Valin81936d52011-08-13 01:44:39 -04001390 /* Override the chosen mode to make sure we meet the requested frame size */
Jean-Marc Valin81936d52011-08-13 01:44:39 -04001391 if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100)
1392 st->mode = MODE_CELT_ONLY;
Jean-Marc Valinc6d0c432013-10-14 17:33:53 -04001393 if (st->lfe)
1394 st->mode = MODE_CELT_ONLY;
Jean-Marc Valin9fd13d62011-10-07 22:50:49 -04001395
Jean-Marc Valin68545562011-08-12 00:30:47 -04001396 if (st->prev_mode > 0 &&
1397 ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ||
1398 (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)))
1399 {
1400 redundancy = 1;
1401 celt_to_silk = (st->mode != MODE_CELT_ONLY);
1402 if (!celt_to_silk)
1403 {
1404 /* Switch to SILK/hybrid if frame size is 10 ms or more*/
1405 if (frame_size >= st->Fs/100)
1406 {
1407 st->mode = st->prev_mode;
1408 to_celt = 1;
1409 } else {
1410 redundancy=0;
1411 }
1412 }
1413 }
Jean-Marc Valin45773d82016-04-27 04:04:50 -04001414
Felicia Lim0962cbe2016-10-27 17:03:36 -07001415 /* When encoding multiframes, we can ask for a switch to CELT only in the last frame. This switch
1416 * is processed above as the requested mode shouldn't interrupt stereo->mono transition. */
1417 if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0
1418 && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)
1419 {
1420 /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
1421 st->silk_mode.toMono = 1;
1422 st->stream_channels = 2;
1423 } else {
1424 st->silk_mode.toMono = 0;
1425 }
1426
Jean-Marc Valin45773d82016-04-27 04:04:50 -04001427 /* Update equivalent rate with mode decision. */
1428 equiv_rate = compute_equiv_rate(st->bitrate_bps, st->stream_channels, st->Fs/frame_size,
Jean-Marc Valin099fc052016-06-20 18:54:06 -04001429 st->use_vbr, st->mode, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
Jean-Marc Valin45773d82016-04-27 04:04:50 -04001430
Jean-Marc Valin68545562011-08-12 00:30:47 -04001431 if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
1432 {
1433 silk_EncControlStruct dummy;
Timothy B. Terriberry39386e02013-11-18 13:30:13 -05001434 silk_InitEncoder( silk_enc, st->arch, &dummy);
Jean-Marc Valin68545562011-08-12 00:30:47 -04001435 prefill=1;
1436 }
1437
Jean-Marc Valin243ff0c2011-05-03 17:06:54 -04001438 /* Automatic (rate-dependent) bandwidth selection */
Jean-Marc Valin09c67662011-05-04 22:34:53 -04001439 if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch)
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001440 {
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001441 const opus_int32 *voice_bandwidth_thresholds, *music_bandwidth_thresholds;
1442 opus_int32 bandwidth_thresholds[8];
Ralph Giles641eea82011-08-02 10:06:59 -07001443 int bandwidth = OPUS_BANDWIDTH_FULLBAND;
Jean-Marc Valin09c67662011-05-04 22:34:53 -04001444
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001445 if (st->channels==2 && st->force_channels!=1)
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001446 {
1447 voice_bandwidth_thresholds = stereo_voice_bandwidth_thresholds;
1448 music_bandwidth_thresholds = stereo_music_bandwidth_thresholds;
1449 } else {
1450 voice_bandwidth_thresholds = mono_voice_bandwidth_thresholds;
1451 music_bandwidth_thresholds = mono_music_bandwidth_thresholds;
1452 }
1453 /* Interpolate bandwidth thresholds depending on voice estimation */
1454 for (i=0;i<8;i++)
1455 {
1456 bandwidth_thresholds[i] = music_bandwidth_thresholds[i]
1457 + ((voice_est*voice_est*(voice_bandwidth_thresholds[i]-music_bandwidth_thresholds[i]))>>14);
1458 }
Ralph Giles641eea82011-08-02 10:06:59 -07001459 do {
1460 int threshold, hysteresis;
1461 threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)];
1462 hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1];
1463 if (!st->first)
1464 {
Jean-Marc Valin691f6f92016-05-31 20:49:41 -04001465 if (st->auto_bandwidth >= bandwidth)
Ralph Giles641eea82011-08-02 10:06:59 -07001466 threshold -= hysteresis;
1467 else
1468 threshold += hysteresis;
1469 }
Jean-Marc Valin45773d82016-04-27 04:04:50 -04001470 if (equiv_rate >= threshold)
Ralph Giles641eea82011-08-02 10:06:59 -07001471 break;
1472 } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND);
Jean-Marc Valin691f6f92016-05-31 20:49:41 -04001473 st->bandwidth = st->auto_bandwidth = bandwidth;
Ralph Giles641eea82011-08-02 10:06:59 -07001474 /* Prevents any transition to SWB/FB until the SILK layer has fully
1475 switched to WB mode and turned the variable LP filter off */
Jean-Marc Valine1be1922011-11-28 22:48:01 -05001476 if (!st->first && st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
Ralph Giles641eea82011-08-02 10:06:59 -07001477 st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001478 }
Jean-Marc Valin955f94c2011-03-08 22:12:43 -05001479
Jean-Marc Valin9ba17432011-10-24 22:41:18 -04001480 if (st->bandwidth>st->max_bandwidth)
1481 st->bandwidth = st->max_bandwidth;
1482
Jean-Marc Valinefe16c52011-09-29 22:02:37 -04001483 if (st->user_bandwidth != OPUS_AUTO)
1484 st->bandwidth = st->user_bandwidth;
1485
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001486 /* This prevents us from using hybrid at unsafe CBR/max rates */
1487 if (st->mode != MODE_CELT_ONLY && max_rate < 15000)
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001488 {
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001489 st->bandwidth = IMIN(st->bandwidth, OPUS_BANDWIDTH_WIDEBAND);
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001490 }
1491
Jean-Marc Valin243ff0c2011-05-03 17:06:54 -04001492 /* Prevents Opus from wasting bits on frequencies that are above
1493 the Nyquist rate of the input signal */
Jean-Marc Valin541df0a2011-05-26 00:22:58 -04001494 if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND)
Ralph Giles641eea82011-08-02 10:06:59 -07001495 st->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -04001496 if (st->Fs <= 16000 && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
Ralph Giles641eea82011-08-02 10:06:59 -07001497 st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -04001498 if (st->Fs <= 12000 && st->bandwidth > OPUS_BANDWIDTH_MEDIUMBAND)
Ralph Giles641eea82011-08-02 10:06:59 -07001499 st->bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -04001500 if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND)
Ralph Giles641eea82011-08-02 10:06:59 -07001501 st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
Jean-Marc Valinc1959e72013-11-08 19:24:10 -05001502#ifndef DISABLE_FLOAT_API
Jean-Marc Valin3ecd9c22013-02-19 00:42:15 -05001503 /* Use detected bandwidth to reduce the encoded bandwidth. */
Jean-Marc Valin23fcd702012-12-21 13:09:43 -05001504 if (st->detected_bandwidth && st->user_bandwidth == OPUS_AUTO)
Jean-Marc Valin7509fdb2012-12-20 22:48:35 -05001505 {
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001506 int min_detected_bandwidth;
1507 /* Makes bandwidth detection more conservative just in case the detector
1508 gets it wrong when we could have coded a high bandwidth transparently.
1509 When operating in SILK/hybrid mode, we don't go below wideband to avoid
1510 more complicated switches that require redundancy. */
Jean-Marc Valinc1959e72013-11-08 19:24:10 -05001511 if (equiv_rate <= 18000*st->stream_channels && st->mode == MODE_CELT_ONLY)
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001512 min_detected_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
Jean-Marc Valinc1959e72013-11-08 19:24:10 -05001513 else if (equiv_rate <= 24000*st->stream_channels && st->mode == MODE_CELT_ONLY)
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001514 min_detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
Jean-Marc Valinc1959e72013-11-08 19:24:10 -05001515 else if (equiv_rate <= 30000*st->stream_channels)
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001516 min_detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valinc1959e72013-11-08 19:24:10 -05001517 else if (equiv_rate <= 44000*st->stream_channels)
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001518 min_detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
Jean-Marc Valin3ecd9c22013-02-19 00:42:15 -05001519 else
Jean-Marc Valin278389d2013-05-17 02:03:33 -04001520 min_detected_bandwidth = OPUS_BANDWIDTH_FULLBAND;
1521
1522 st->detected_bandwidth = IMAX(st->detected_bandwidth, min_detected_bandwidth);
1523 st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth);
Jean-Marc Valin7509fdb2012-12-20 22:48:35 -05001524 }
1525#endif
Jean-Marc Valin2b011b62016-06-21 12:38:25 -04001526 st->silk_mode.LBRR_coded = decide_fec(st->silk_mode.useInBandFEC, st->silk_mode.packetLossPercentage,
1527 st->silk_mode.LBRR_coded, st->mode, &st->bandwidth, equiv_rate);
Jean-Marc Valinb3eba242012-12-20 23:11:53 -05001528 celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth));
Jean-Marc Valin955f94c2011-03-08 22:12:43 -05001529
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001530 /* CELT mode doesn't support mediumband, use wideband instead */
1531 if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
1532 st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -04001533 if (st->lfe)
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -04001534 st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001535
Felicia Lim0962cbe2016-10-27 17:03:36 -07001536 curr_bandwidth = st->bandwidth;
1537
1538 /* Chooses the appropriate mode for speech
1539 *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */
1540 if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND)
1541 st->mode = MODE_HYBRID;
1542 if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
1543 st->mode = MODE_SILK_ONLY;
1544
1545 /* Can't support higher than >60 ms frames, and >20 ms when in Hybrid or CELT-only modes */
1546 if ((frame_size > st->Fs/50 && (st->mode != MODE_SILK_ONLY)) || frame_size > 3*st->Fs/50)
Jean-Marc Valine4336a52011-09-08 18:19:50 -04001547 {
Felicia Lim8bca1542016-09-22 11:06:11 +02001548 int enc_frame_size;
Jean-Marc Valine4336a52011-09-08 18:19:50 -04001549 int nb_frames;
Felicia Lim8bca1542016-09-22 11:06:11 +02001550
Felicia Lim0962cbe2016-10-27 17:03:36 -07001551 if (st->mode == MODE_SILK_ONLY)
1552 {
1553 if (frame_size == 2*st->Fs/25) /* 80 ms -> 2x 40 ms */
1554 enc_frame_size = st->Fs/25;
1555 if (frame_size == 3*st->Fs/25) /* 120 ms -> 2x 60 ms */
1556 enc_frame_size = 3*st->Fs/50;
1557 else /* 100 ms -> 5x 20 ms */
1558 enc_frame_size = st->Fs/50;
1559 }
1560 else
1561 enc_frame_size = st->Fs/50;
1562
1563 nb_frames = frame_size/enc_frame_size;
Jean-Marc Valind970a852011-09-08 21:41:29 -04001564
Jean-Marc Valinc2b34412013-10-28 21:48:50 -04001565#ifndef DISABLE_FLOAT_API
Jean-Marc Valin29254442013-09-28 19:29:23 -04001566 if (analysis_read_pos_bak!= -1)
1567 {
1568 st->analysis.read_pos = analysis_read_pos_bak;
1569 st->analysis.read_subframe = analysis_read_subframe_bak;
1570 }
Jean-Marc Valinc2b34412013-10-28 21:48:50 -04001571#endif
Jean-Marc Valin1e22a4b2011-10-07 22:29:38 -04001572
Felicia Lim8bca1542016-09-22 11:06:11 +02001573 ret = encode_multiframe_packet(st, pcm, nb_frames, enc_frame_size, data,
1574 out_data_bytes, to_celt, lsb_depth, float_api);
Jean-Marc Valind970a852011-09-08 21:41:29 -04001575
Jean-Marc Valine4336a52011-09-08 18:19:50 -04001576 RESTORE_STACK;
1577 return ret;
1578 }
Jean-Marc Valin81936d52011-08-13 01:44:39 -04001579
Mark Harris1fd53f92016-11-02 06:16:50 -07001580 /* For the first frame at a new SILK bandwidth */
1581 if (st->silk_bw_switch)
1582 {
1583 redundancy = 1;
1584 celt_to_silk = 1;
1585 st->silk_bw_switch = 0;
1586 prefill=1;
1587 }
1588
Jean-Marc Valinac9fabc2016-09-07 22:04:49 -04001589 /* If we decided to go with CELT, make sure redundancy is off, no matter what
1590 we decided earlier. */
1591 if (st->mode == MODE_CELT_ONLY)
Jean-Marc Valinac9fabc2016-09-07 22:04:49 -04001592 redundancy = 0;
Mark Harris1fd53f92016-11-02 06:16:50 -07001593
1594 if (redundancy)
1595 {
1596 /* Fair share of the max size allowed */
1597 redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200));
1598 /* For VBR, target the actual bitrate (subject to the limit above) */
1599 if (st->use_vbr)
1600 redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600);
Jean-Marc Valinac9fabc2016-09-07 22:04:49 -04001601 }
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001602
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001603 /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001604 bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001605
Ralph Giles641eea82011-08-02 10:06:59 -07001606 data += 1;
Jean-Marc Valin606250a2011-02-15 14:31:21 -05001607
Ralph Giles641eea82011-08-02 10:06:59 -07001608 ec_enc_init(&enc, data, max_data_bytes-1);
Jean-Marc Valin24af3032010-06-30 14:29:45 -04001609
Jean-Marc Valin1a2e7652011-11-06 23:27:16 -05001610 ALLOC(pcm_buf, (total_buffer+frame_size)*st->channels, opus_val16);
Jean-Marc Valinff072002013-12-08 23:31:30 -05001611 OPUS_COPY(pcm_buf, &st->delay_buffer[(st->encoder_buffer-total_buffer)*st->channels], total_buffer*st->channels);
Jean-Marc Valin957f7f12011-09-01 18:02:43 -04001612
1613 if (st->mode == MODE_CELT_ONLY)
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -07001614 hp_freq_smth1 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -04001615 else
1616 hp_freq_smth1 = ((silk_encoder*)silk_enc)->state_Fxx[0].sCmn.variable_HP_smth1_Q15;
1617
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -07001618 st->variable_HP_smth2_Q15 = silk_SMLAWB( st->variable_HP_smth2_Q15,
Jean-Marc Valin957f7f12011-09-01 18:02:43 -04001619 hp_freq_smth1 - st->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) );
1620
1621 /* convert from log scale to Hertz */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -07001622 cutoff_Hz = silk_log2lin( silk_RSHIFT( st->variable_HP_smth2_Q15, 8 ) );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -04001623
1624 if (st->application == OPUS_APPLICATION_VOIP)
1625 {
Jean-Marc Valin1a2e7652011-11-06 23:27:16 -05001626 hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
Jean-Marc Valin957f7f12011-09-01 18:02:43 -04001627 } else {
Jean-Marc Valindb13c382011-12-23 11:58:43 -05001628 dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
Jean-Marc Valin957f7f12011-09-01 18:02:43 -04001629 }
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001630#ifndef FIXED_POINT
1631 if (float_api)
1632 {
Jean-Marc Valin66b7fe02013-12-09 13:54:41 -05001633 opus_val32 sum;
xiangmingzhuc95c9a02014-04-30 15:48:07 +08001634 sum = celt_inner_prod(&pcm_buf[total_buffer*st->channels], &pcm_buf[total_buffer*st->channels], frame_size*st->channels, st->arch);
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001635 /* This should filter out both NaNs and ridiculous signals that could
1636 cause NaNs further down. */
Jean-Marc Valin122971b2013-12-10 13:55:35 -05001637 if (!(sum < 1e9f) || celt_isnan(sum))
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -04001638 {
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001639 OPUS_CLEAR(&pcm_buf[total_buffer*st->channels], frame_size*st->channels);
Jean-Marc Valin7c49ad02015-10-07 09:17:50 -04001640 st->hp_mem[0] = st->hp_mem[1] = st->hp_mem[2] = st->hp_mem[3] = 0;
1641 }
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05001642 }
1643#endif
Jean-Marc Valin7ebacf42012-11-13 02:24:07 -05001644
Jean-Marc Valin1a2e7652011-11-06 23:27:16 -05001645
Ralph Giles641eea82011-08-02 10:06:59 -07001646 /* SILK processing */
Jean-Marc Valinf68799b2012-07-12 17:36:11 -04001647 HB_gain = Q15ONE;
Jean-Marc Valin606250a2011-02-15 14:31:21 -05001648 if (st->mode != MODE_CELT_ONLY)
1649 {
Jean-Marc Valinf68799b2012-07-12 17:36:11 -04001650 opus_int32 total_bitRate, celt_rate;
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001651#ifdef FIXED_POINT
1652 const opus_int16 *pcm_silk;
1653#else
1654 VARDECL(opus_int16, pcm_silk);
1655 ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
1656#endif
Koen Vos0b00b312012-07-12 14:55:49 -04001657
1658 /* Distribute bits between SILK and CELT */
1659 total_bitRate = 8 * bytes_target * frame_rate;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001660 if( st->mode == MODE_HYBRID ) {
Koen Vos0b00b312012-07-12 14:55:49 -04001661 /* Base rate for SILK */
Jean-Marc Valin66f3ef32015-12-24 13:03:28 -05001662 st->silk_mode.bitRate = compute_silk_rate_for_hybrid(total_bitRate,
Jean-Marc Valinb3c9e792016-06-21 13:37:29 -04001663 curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
Jean-Marc Valinca5bf5b2013-11-18 23:00:36 -05001664 if (!st->energy_masking)
1665 {
1666 /* Increasingly attenuate high band when it gets allocated fewer bits */
1667 celt_rate = total_bitRate - st->silk_mode.bitRate;
Jean-Marc Valinecfdb282016-04-22 16:13:46 -04001668 HB_gain = Q15ONE - SHR32(celt_exp2(-celt_rate * QCONST16(1.f/1024, 10)), 1);
Jean-Marc Valinca5bf5b2013-11-18 23:00:36 -05001669 }
Koen Vos0b00b312012-07-12 14:55:49 -04001670 } else {
1671 /* SILK gets all bits */
1672 st->silk_mode.bitRate = total_bitRate;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001673 }
Jean-Marc Valin862e1822010-07-20 12:19:00 -04001674
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04001675 /* Surround masking for SILK */
1676 if (st->energy_masking && st->use_vbr && !st->lfe)
1677 {
1678 opus_val32 mask_sum=0;
1679 opus_val16 masking_depth;
1680 opus_int32 rate_offset;
1681 int c;
1682 int end = 17;
1683 opus_int16 srate = 16000;
1684 if (st->bandwidth == OPUS_BANDWIDTH_NARROWBAND)
1685 {
1686 end = 13;
1687 srate = 8000;
1688 } else if (st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
1689 {
1690 end = 15;
1691 srate = 12000;
1692 }
1693 for (c=0;c<st->channels;c++)
1694 {
1695 for(i=0;i<end;i++)
Jean-Marc Valinae7dc8a2013-09-13 15:05:50 -04001696 {
1697 opus_val16 mask;
1698 mask = MAX16(MIN16(st->energy_masking[21*c+i],
Jean-Marc Valin93e10962013-11-25 01:52:08 -05001699 QCONST16(.5f, DB_SHIFT)), -QCONST16(2.0f, DB_SHIFT));
Jean-Marc Valinae7dc8a2013-09-13 15:05:50 -04001700 if (mask > 0)
1701 mask = HALF16(mask);
1702 mask_sum += mask;
1703 }
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04001704 }
1705 /* Conservative rate reduction, we cut the masking in half */
Jean-Marc Valin93e10962013-11-25 01:52:08 -05001706 masking_depth = mask_sum / end*st->channels;
1707 masking_depth += QCONST16(.2f, DB_SHIFT);
Jean-Marc Valin6bc3e3c2013-11-17 22:35:15 -05001708 rate_offset = (opus_int32)PSHR32(MULT16_16(srate, masking_depth), DB_SHIFT);
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04001709 rate_offset = MAX32(rate_offset, -2*st->silk_mode.bitRate/3);
Jean-Marc Valin93e10962013-11-25 01:52:08 -05001710 /* Split the rate change between the SILK and CELT part for hybrid. */
1711 if (st->bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND || st->bandwidth==OPUS_BANDWIDTH_FULLBAND)
1712 st->silk_mode.bitRate += 3*rate_offset/5;
1713 else
1714 st->silk_mode.bitRate += rate_offset;
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04001715 }
1716
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001717 st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001718 st->silk_mode.nChannelsAPI = st->channels;
1719 st->silk_mode.nChannelsInternal = st->stream_channels;
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001720 if (curr_bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
Ralph Giles641eea82011-08-02 10:06:59 -07001721 st->silk_mode.desiredInternalSampleRate = 8000;
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001722 } else if (curr_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
Ralph Giles641eea82011-08-02 10:06:59 -07001723 st->silk_mode.desiredInternalSampleRate = 12000;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001724 } else {
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001725 silk_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND );
Jean-Marc Valind8f90972011-04-27 10:06:53 -04001726 st->silk_mode.desiredInternalSampleRate = 16000;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001727 }
1728 if( st->mode == MODE_HYBRID ) {
1729 /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
Koen Vos1e1562c2011-02-14 15:04:59 -05001730 st->silk_mode.minInternalSampleRate = 16000;
1731 } else {
1732 st->silk_mode.minInternalSampleRate = 8000;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001733 }
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001734
Jean-Marc Valin0e69e4e2016-04-17 03:20:46 -04001735 st->silk_mode.maxInternalSampleRate = 16000;
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001736 if (st->mode == MODE_SILK_ONLY)
1737 {
Jean-Marc Valin33bd6aa2011-10-24 11:53:01 -04001738 opus_int32 effective_max_rate = max_rate;
1739 if (frame_rate > 50)
1740 effective_max_rate = effective_max_rate*2/3;
Jean-Marc Valin0e69e4e2016-04-17 03:20:46 -04001741 if (effective_max_rate < 8000)
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001742 {
1743 st->silk_mode.maxInternalSampleRate = 12000;
1744 st->silk_mode.desiredInternalSampleRate = IMIN(12000, st->silk_mode.desiredInternalSampleRate);
1745 }
Jean-Marc Valin0e69e4e2016-04-17 03:20:46 -04001746 if (effective_max_rate < 7000)
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001747 {
1748 st->silk_mode.maxInternalSampleRate = 8000;
1749 st->silk_mode.desiredInternalSampleRate = IMIN(8000, st->silk_mode.desiredInternalSampleRate);
1750 }
Jean-Marc Valin99ca4b32011-10-20 14:30:30 -04001751 }
Jean-Marc Valinb5be8262010-11-12 06:47:46 +08001752
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001753 st->silk_mode.useCBR = !st->use_vbr;
1754
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001755 /* Call SILK encoder for the low band */
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001756
Jean-Marc Valin6d062842016-10-27 00:11:26 -04001757 /* Max bits for SILK, counting ToC, redundancy bytes, and optionally redundancy. */
Mark Harris20bf3b32016-11-02 06:18:25 -07001758 st->silk_mode.maxBits = (max_data_bytes-1)*8;
1759 if (redundancy && redundancy_bytes >= 2)
Jean-Marc Valin6d062842016-10-27 00:11:26 -04001760 {
1761 /* Counting 1 bit for redundancy position and 20 bits for flag+size (only for hybrid). */
Mark Harris20bf3b32016-11-02 06:18:25 -07001762 st->silk_mode.maxBits -= redundancy_bytes*8 + 1;
Jean-Marc Valin6d062842016-10-27 00:11:26 -04001763 if (st->mode == MODE_HYBRID)
1764 st->silk_mode.maxBits -= 20;
1765 }
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001766 if (st->silk_mode.useCBR)
1767 {
Jean-Marc Valinf6c4f642016-06-02 17:54:14 -04001768 if (st->mode == MODE_HYBRID)
1769 {
Jean-Marc Valin6d062842016-10-27 00:11:26 -04001770 st->silk_mode.maxBits = IMIN(st->silk_mode.maxBits, st->silk_mode.bitRate * frame_size / st->Fs);
Jean-Marc Valinf6c4f642016-06-02 17:54:14 -04001771 }
1772 } else {
1773 /* Constrained VBR. */
1774 if (st->mode == MODE_HYBRID)
1775 {
1776 /* Compute SILK bitrate corresponding to the max total bits available */
Jean-Marc Valin6d062842016-10-27 00:11:26 -04001777 opus_int32 maxBitRate = compute_silk_rate_for_hybrid(st->silk_mode.maxBits*st->Fs / frame_size,
Jean-Marc Valinb3c9e792016-06-21 13:37:29 -04001778 curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
Jean-Marc Valinf6c4f642016-06-02 17:54:14 -04001779 st->silk_mode.maxBits = maxBitRate * frame_size / st->Fs;
1780 }
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001781 }
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04001782
Jean-Marc Valine3de5052011-02-20 12:23:48 -05001783 if (prefill)
Jean-Marc Valina93f5012011-03-03 15:50:08 -05001784 {
Jean-Marc Valin59354a72012-03-08 12:19:07 -05001785 opus_int32 zero=0;
Jean-Marc Valin61e9eb12013-02-06 18:10:51 -05001786 int prefill_offset;
Jean-Marc Valin61e9eb12013-02-06 18:10:51 -05001787 /* Use a smooth onset for the SILK prefill to avoid the encoder trying to encode
1788 a discontinuity. The exact location is what we need to avoid leaving any "gap"
1789 in the audio when mixing with the redundant CELT frame. Here we can afford to
1790 overwrite st->delay_buffer because the only thing that uses it before it gets
1791 rewritten is tmp_prefill[] and even then only the part after the ramp really
1792 gets used (rather than sent to the encoder and discarded) */
1793 prefill_offset = st->channels*(st->encoder_buffer-st->delay_compensation-st->Fs/400);
1794 gain_fade(st->delay_buffer+prefill_offset, st->delay_buffer+prefill_offset,
1795 0, Q15ONE, celt_mode->overlap, st->Fs/400, st->channels, celt_mode->window, st->Fs);
Jean-Marc Valinff072002013-12-08 23:31:30 -05001796 OPUS_CLEAR(st->delay_buffer, prefill_offset);
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001797#ifdef FIXED_POINT
1798 pcm_silk = st->delay_buffer;
1799#else
1800 for (i=0;i<st->encoder_buffer*st->channels;i++)
Ralph Giles04cca282011-08-24 00:29:29 -04001801 pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]);
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001802#endif
1803 silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 );
Jean-Marc Valina93f5012011-03-03 15:50:08 -05001804 }
Jean-Marc Valine3de5052011-02-20 12:23:48 -05001805
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001806#ifdef FIXED_POINT
Jean-Marc Valin1a2e7652011-11-06 23:27:16 -05001807 pcm_silk = pcm_buf+total_buffer*st->channels;
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001808#else
1809 for (i=0;i<frame_size*st->channels;i++)
Jean-Marc Valin1a2e7652011-11-06 23:27:16 -05001810 pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]);
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001811#endif
1812 ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 );
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001813 if( ret ) {
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001814 /*fprintf (stderr, "SILK encode error: %d\n", ret);*/
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001815 /* Handle error */
Jean-Marc Valinc7921082012-03-05 19:56:13 -05001816 RESTORE_STACK;
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001817 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001818 }
Felicia Lim33698ee2016-10-26 16:48:38 -07001819
Jean-Marc Valin69bfc672011-08-29 21:46:17 -04001820 /* Extract SILK internal bandwidth for signaling in first byte */
1821 if( st->mode == MODE_SILK_ONLY ) {
1822 if( st->silk_mode.internalSampleRate == 8000 ) {
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001823 curr_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
Jean-Marc Valin69bfc672011-08-29 21:46:17 -04001824 } else if( st->silk_mode.internalSampleRate == 12000 ) {
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001825 curr_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
Jean-Marc Valin69bfc672011-08-29 21:46:17 -04001826 } else if( st->silk_mode.internalSampleRate == 16000 ) {
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001827 curr_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valin69bfc672011-08-29 21:46:17 -04001828 }
1829 } else {
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -07001830 silk_assert( st->silk_mode.internalSampleRate == 16000 );
Jean-Marc Valin69bfc672011-08-29 21:46:17 -04001831 }
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001832
Felicia Lim0962cbe2016-10-27 17:03:36 -07001833 st->silk_mode.opusCanSwitch = st->silk_mode.switchReady && !st->nonfinal_frame;
Felicia Lim33698ee2016-10-26 16:48:38 -07001834
1835 if (nBytes==0)
1836 {
1837 st->rangeFinal = 0;
1838 data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
1839 RESTORE_STACK;
1840 return 1;
1841 }
1842
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001843 /* FIXME: How do we allocate the redundancy for CBR? */
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001844 if (st->silk_mode.opusCanSwitch)
1845 {
1846 redundancy = 1;
1847 celt_to_silk = 0;
1848 st->silk_bw_switch = 1;
1849 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001850 }
Jean-Marc Valin67008d22010-07-20 11:13:30 -04001851
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001852 /* CELT processing */
Ralph Giles641eea82011-08-02 10:06:59 -07001853 {
1854 int endband=21;
Jean-Marc Valine2d1ef12010-07-06 15:39:19 -04001855
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001856 switch(curr_bandwidth)
Ralph Giles641eea82011-08-02 10:06:59 -07001857 {
1858 case OPUS_BANDWIDTH_NARROWBAND:
1859 endband = 13;
1860 break;
1861 case OPUS_BANDWIDTH_MEDIUMBAND:
Ralph Giles04cca282011-08-24 00:29:29 -04001862 case OPUS_BANDWIDTH_WIDEBAND:
1863 endband = 17;
1864 break;
Ralph Giles641eea82011-08-02 10:06:59 -07001865 case OPUS_BANDWIDTH_SUPERWIDEBAND:
1866 endband = 19;
1867 break;
1868 case OPUS_BANDWIDTH_FULLBAND:
1869 endband = 21;
1870 break;
1871 }
1872 celt_encoder_ctl(celt_enc, CELT_SET_END_BAND(endband));
1873 celt_encoder_ctl(celt_enc, CELT_SET_CHANNELS(st->stream_channels));
1874 }
Jean-Marc Valin23f3a1f2011-10-30 22:41:32 -04001875 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
Ralph Giles641eea82011-08-02 10:06:59 -07001876 if (st->mode != MODE_SILK_ONLY)
1877 {
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001878 opus_val32 celt_pred=2;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001879 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05001880 /* We may still decide to disable prediction later */
1881 if (st->silk_mode.reducedDependency)
1882 celt_pred = 0;
1883 celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred));
Jean-Marc Valine2a09db2011-03-02 17:54:43 -05001884
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001885 if (st->mode == MODE_HYBRID)
1886 {
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001887 if( st->use_vbr ) {
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05001888 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps-st->silk_mode.bitRate));
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05001889 celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(0));
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001890 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001891 } else {
Jean-Marc Valind9ad6e12011-02-01 18:08:41 -05001892 if (st->use_vbr)
1893 {
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001894 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1));
1895 celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint));
Jean-Marc Valin132ed592016-11-04 11:41:13 -04001896 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps));
Jean-Marc Valind9ad6e12011-02-01 18:08:41 -05001897 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001898 }
Ralph Giles641eea82011-08-02 10:06:59 -07001899 }
Jean-Marc Valinc8a20b72010-07-21 14:07:11 -04001900
Jean-Marc Valine22cc272011-10-14 13:48:17 -04001901 ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16);
Jean-Marc Valine6a4ece2011-10-19 01:56:38 -04001902 if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0)
Jean-Marc Valine22cc272011-10-14 13:48:17 -04001903 {
Jean-Marc Valinff072002013-12-08 23:31:30 -05001904 OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400);
Jean-Marc Valine22cc272011-10-14 13:48:17 -04001905 }
1906
Jean-Marc Valinff072002013-12-08 23:31:30 -05001907 if (st->channels*(st->encoder_buffer-(frame_size+total_buffer)) > 0)
1908 {
1909 OPUS_MOVE(st->delay_buffer, &st->delay_buffer[st->channels*frame_size], st->channels*(st->encoder_buffer-frame_size-total_buffer));
1910 OPUS_COPY(&st->delay_buffer[st->channels*(st->encoder_buffer-frame_size-total_buffer)],
1911 &pcm_buf[0],
1912 (frame_size+total_buffer)*st->channels);
1913 } else {
1914 OPUS_COPY(st->delay_buffer, &pcm_buf[(frame_size+total_buffer-st->encoder_buffer)*st->channels], st->encoder_buffer*st->channels);
1915 }
Jean-Marc Valinf68799b2012-07-12 17:36:11 -04001916 /* gain_fade() and stereo_fade() need to be after the buffer copying
1917 because we don't want any of this to affect the SILK part */
1918 if( st->prev_HB_gain < Q15ONE || HB_gain < Q15ONE ) {
Jean-Marc Valinbb43b8b2012-12-17 18:02:56 -05001919 gain_fade(pcm_buf, pcm_buf,
Jean-Marc Valinf68799b2012-07-12 17:36:11 -04001920 st->prev_HB_gain, HB_gain, celt_mode->overlap, frame_size, st->channels, celt_mode->window, st->Fs);
1921 }
1922 st->prev_HB_gain = HB_gain;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001923 if (st->mode != MODE_HYBRID || st->stream_channels==1)
Jean-Marc Valin8dcf4ac2015-11-27 19:10:24 -05001924 st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-24000));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04001925 if( !st->energy_masking && st->channels == 2 ) {
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001926 /* Apply stereo width reduction (at low bitrates) */
1927 if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) {
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001928 opus_val16 g1, g2;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001929 g1 = st->hybrid_stereo_width_Q14;
Koen Vos854fe702011-10-09 20:34:41 -04001930 g2 = (opus_val16)(st->silk_mode.stereoWidth_Q14);
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001931#ifdef FIXED_POINT
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001932 g1 = g1==16384 ? Q15ONE : SHL16(g1,1);
1933 g2 = g2==16384 ? Q15ONE : SHL16(g2,1);
Jean-Marc Valinab964572011-10-13 16:18:24 -04001934#else
Gregory Maxwell37f56592012-07-17 17:40:55 -04001935 g1 *= (1.f/16384);
1936 g2 *= (1.f/16384);
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001937#endif
Jean-Marc Valinbb43b8b2012-12-17 18:02:56 -05001938 stereo_fade(pcm_buf, pcm_buf, g1, g2, celt_mode->overlap,
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001939 frame_size, st->channels, celt_mode->window, st->Fs);
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001940 st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14;
1941 }
1942 }
1943
Jean-Marc Valine9b53212011-10-13 16:24:11 -04001944 if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) <= 8*(max_data_bytes-1))
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001945 {
Jean-Marc Valin591b7492011-10-08 10:22:10 -04001946 /* For SILK mode, the redundancy is inferred from the length */
Mark Harris20bf3b32016-11-02 06:18:25 -07001947 if (st->mode == MODE_HYBRID)
Jean-Marc Valin591b7492011-10-08 10:22:10 -04001948 ec_enc_bit_logp(&enc, redundancy, 12);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001949 if (redundancy)
1950 {
Jean-Marc Valine5736ae2011-09-05 10:28:27 -04001951 int max_redundancy;
1952 ec_enc_bit_logp(&enc, celt_to_silk, 1);
Jean-Marc Valin591b7492011-10-08 10:22:10 -04001953 if (st->mode == MODE_HYBRID)
Mark Harris20bf3b32016-11-02 06:18:25 -07001954 {
1955 /* Reserve the 8 bits needed for the redundancy length,
1956 and at least a few bits for CELT if possible */
1957 max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+8+3+7)>>3);
1958 max_redundancy = IMIN(max_redundancy, redundancy_bytes);
1959 }
Jean-Marc Valin591b7492011-10-08 10:22:10 -04001960 else
1961 max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3);
Jean-Marc Valin51ac8e62011-08-15 22:06:02 -04001962 /* Target the same bit-rate for redundancy as for the rest,
1963 up to a max of 257 bytes */
Jean-Marc Valine5736ae2011-09-05 10:28:27 -04001964 redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600);
1965 redundancy_bytes = IMIN(257, IMAX(2, redundancy_bytes));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001966 if (st->mode == MODE_HYBRID)
Ralph Giles04cca282011-08-24 00:29:29 -04001967 ec_enc_uint(&enc, redundancy_bytes-2, 256);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001968 }
Jean-Marc Valine5736ae2011-09-05 10:28:27 -04001969 } else {
1970 redundancy = 0;
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001971 }
1972
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001973 if (!redundancy)
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001974 {
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04001975 st->silk_bw_switch = 0;
Jean-Marc Valin6b459742012-09-20 22:00:22 -04001976 redundancy_bytes = 0;
1977 }
Gregory Maxwell7d1df732011-09-05 11:28:28 -04001978 if (st->mode != MODE_CELT_ONLY)start_band=17;
1979
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001980 if (st->mode == MODE_SILK_ONLY)
1981 {
1982 ret = (ec_tell(&enc)+7)>>3;
1983 ec_enc_done(&enc);
1984 nb_compr_bytes = ret;
Jean-Marc Valin51ac8e62011-08-15 22:06:02 -04001985 } else {
Mark Harris20bf3b32016-11-02 06:18:25 -07001986 nb_compr_bytes = (max_data_bytes-1)-redundancy_bytes;
Jean-Marc Valin51ac8e62011-08-15 22:06:02 -04001987 ec_enc_shrink(&enc, nb_compr_bytes);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001988 }
1989
Jean-Marc Valin3ab03e02013-09-06 16:00:39 -04001990#ifndef DISABLE_FLOAT_API
Jean-Marc Valinf8eb44e2013-05-17 23:22:09 -04001991 if (redundancy || st->mode != MODE_SILK_ONLY)
Jean-Marc Valin91904a42013-09-05 21:34:43 -04001992 celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info));
Jean-Marc Valinf8eb44e2013-05-17 23:22:09 -04001993#endif
Jean-Marc Valin61714e92016-04-23 00:34:53 -04001994 if (st->mode == MODE_HYBRID) {
1995 SILKInfo info;
1996 info.signalType = st->silk_mode.signalType;
1997 info.offset = st->silk_mode.offset;
1998 celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO(&info));
1999 } else {
2000 celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO((SILKInfo*)NULL));
2001 }
Jean-Marc Valin51ac8e62011-08-15 22:06:02 -04002002
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002003 /* 5 ms redundant frame for CELT->SILK */
2004 if (redundancy && celt_to_silk)
2005 {
Jean-Marc Valinf340bba2011-10-27 20:33:48 -04002006 int err;
Jean-Marc Valin5095c472011-05-05 19:47:48 -04002007 celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002008 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05002009 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
Jean-Marc Valinbb43b8b2012-12-17 18:02:56 -05002010 err = celt_encode_with_ec(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes, NULL);
Jean-Marc Valinf340bba2011-10-27 20:33:48 -04002011 if (err < 0)
Jean-Marc Valinc7921082012-03-05 19:56:13 -05002012 {
2013 RESTORE_STACK;
2014 return OPUS_INTERNAL_ERROR;
2015 }
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002016 celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng));
2017 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002018 }
2019
Jean-Marc Valin5095c472011-05-05 19:47:48 -04002020 celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(start_band));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002021
2022 if (st->mode != MODE_SILK_ONLY)
Ralph Giles641eea82011-08-02 10:06:59 -07002023 {
Jean-Marc Valine6a4ece2011-10-19 01:56:38 -04002024 if (st->mode != st->prev_mode && st->prev_mode > 0)
2025 {
2026 unsigned char dummy[2];
2027 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
2028
2029 /* Prefilling */
2030 celt_encode_with_ec(celt_enc, tmp_prefill, st->Fs/400, dummy, 2, NULL);
2031 celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
2032 }
Mark Harris20bf3b32016-11-02 06:18:25 -07002033 /* If false, we already busted the budget and we'll end up with a "PLC frame" */
Jean-Marc Valine1be1922011-11-28 22:48:01 -05002034 if (ec_tell(&enc) <= 8*nb_compr_bytes)
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002035 {
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05002036 /* Set the bitrate again if it was overridden in the redundancy code above*/
2037 if (redundancy && celt_to_silk && st->mode==MODE_HYBRID && st->use_vbr)
2038 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps-st->silk_mode.bitRate));
2039 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(st->use_vbr));
Jean-Marc Valinbb43b8b2012-12-17 18:02:56 -05002040 ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002041 if (ret < 0)
Jean-Marc Valinc7921082012-03-05 19:56:13 -05002042 {
2043 RESTORE_STACK;
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002044 return OPUS_INTERNAL_ERROR;
Jean-Marc Valinc7921082012-03-05 19:56:13 -05002045 }
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05002046 /* Put CELT->SILK redundancy data in the right place. */
2047 if (redundancy && celt_to_silk && st->mode==MODE_HYBRID && st->use_vbr)
2048 {
Jean-Marc Valinae5f5cc2016-09-20 01:44:22 -04002049 OPUS_MOVE(data+ret, data+nb_compr_bytes, redundancy_bytes);
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05002050 nb_compr_bytes = nb_compr_bytes+redundancy_bytes;
2051 }
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002052 }
Ralph Giles641eea82011-08-02 10:06:59 -07002053 }
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002054
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002055 /* 5 ms redundant frame for SILK->CELT */
2056 if (redundancy && !celt_to_silk)
2057 {
Jean-Marc Valinf340bba2011-10-27 20:33:48 -04002058 int err;
Jean-Marc Valine6a4ece2011-10-19 01:56:38 -04002059 unsigned char dummy[2];
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002060 int N2, N4;
2061 N2 = st->Fs/200;
2062 N4 = st->Fs/400;
2063
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002064 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
Jean-Marc Valin5095c472011-05-05 19:47:48 -04002065 celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
2066 celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05002067 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
2068 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002069
Jean-Marc Valinbcd6aba2015-12-06 10:50:15 -05002070 if (st->mode == MODE_HYBRID)
2071 {
2072 /* Shrink packet to what the encoder actually used. */
2073 nb_compr_bytes = ret;
2074 ec_enc_shrink(&enc, nb_compr_bytes);
2075 }
Jean-Marc Valin92675062011-09-11 22:00:46 -04002076 /* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */
Jean-Marc Valinbb43b8b2012-12-17 18:02:56 -05002077 celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, dummy, 2, NULL);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002078
Jean-Marc Valinbb43b8b2012-12-17 18:02:56 -05002079 err = celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes, NULL);
Jean-Marc Valinf340bba2011-10-27 20:33:48 -04002080 if (err < 0)
Jean-Marc Valinc7921082012-03-05 19:56:13 -05002081 {
2082 RESTORE_STACK;
2083 return OPUS_INTERNAL_ERROR;
2084 }
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002085 celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002086 }
2087
2088
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002089
Ralph Giles641eea82011-08-02 10:06:59 -07002090 /* Signalling the mode in the first byte */
2091 data--;
Jean-Marc Valin3b2aee02011-10-21 23:21:34 -04002092 data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
Jean-Marc Valin57de8a32010-09-07 17:37:56 -04002093
Jean-Marc Valin06cee2b2011-08-19 16:11:41 -04002094 st->rangeFinal = enc.rng ^ redundant_rng;
Ralph Giles3f0962c2011-07-29 14:01:54 -07002095
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05002096 if (to_celt)
2097 st->prev_mode = MODE_CELT_ONLY;
2098 else
2099 st->prev_mode = st->mode;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04002100 st->prev_channels = st->stream_channels;
Gregory Maxwell220a7d42011-10-01 20:30:16 -04002101 st->prev_framesize = frame_size;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04002102
Jean-Marc Valinc1673fa2011-04-28 08:04:20 -04002103 st->first = 0;
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002104
Felicia Lim36481342016-05-16 15:29:53 +02002105 /* DTX decision */
2106#ifndef DISABLE_FLOAT_API
2107 if (st->use_dtx && (analysis_info.valid || is_silence))
2108 {
Jean-Marc Valin9f3883a2016-08-25 14:24:38 -04002109 if (decide_dtx_mode(analysis_info.activity_probability, &st->nb_no_activity_frames,
2110 st->peak_signal_energy, pcm, frame_size, st->channels, is_silence, st->arch))
Felicia Lim36481342016-05-16 15:29:53 +02002111 {
2112 st->rangeFinal = 0;
2113 data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
2114 RESTORE_STACK;
2115 return 1;
2116 }
2117 }
2118#endif
2119
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002120 /* In the unlikely case that the SILK encoder busted its target, tell
2121 the decoder to call the PLC */
2122 if (ec_tell(&enc) > (max_data_bytes-1)*8)
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04002123 {
Vincent Penquerc'h037918a2011-11-22 15:12:44 +00002124 if (max_data_bytes < 2)
2125 {
2126 RESTORE_STACK;
2127 return OPUS_BUFFER_TOO_SMALL;
2128 }
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002129 data[1] = 0;
2130 ret = 1;
2131 st->rangeFinal = 0;
Jean-Marc Valine1be1922011-11-28 22:48:01 -05002132 } else if (st->mode==MODE_SILK_ONLY&&!redundancy)
2133 {
2134 /*When in LPC only mode it's perfectly
2135 reasonable to strip off trailing zero bytes as
2136 the required range decoder behavior is to
2137 fill these in. This can't be done when the MDCT
2138 modes are used because the decoder needs to know
2139 the actual length for allocation purposes.*/
2140 while(ret>2&&data[ret]==0)ret--;
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002141 }
2142 /* Count ToC and redundancy */
2143 ret += 1+redundancy_bytes;
Jean-Marc Valin21b131f2013-11-21 14:42:00 -05002144 if (!st->use_vbr)
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002145 {
Jean-Marc Valinc5635d22013-11-13 14:08:22 -05002146 if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK)
Jean-Marc Valinc7921082012-03-05 19:56:13 -05002147 {
2148 RESTORE_STACK;
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002149 return OPUS_INTERNAL_ERROR;
Jean-Marc Valinc7921082012-03-05 19:56:13 -05002150 }
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002151 ret = max_data_bytes;
Jean-Marc Valin294bfec2011-10-20 00:39:41 -04002152 }
Jean-Marc Valin44e27dd2011-08-29 23:35:17 -04002153 RESTORE_STACK;
Jean-Marc Valinbe236b12011-10-29 02:12:26 -04002154 return ret;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002155}
2156
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002157#ifdef FIXED_POINT
2158
2159#ifndef DISABLE_FLOAT_API
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002160opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
Gregory Maxwelle7028172011-11-19 23:58:09 -05002161 unsigned char *data, opus_int32 max_data_bytes)
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002162{
2163 int i, ret;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002164 int frame_size;
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002165 VARDECL(opus_int16, in);
2166 ALLOC_STACK;
2167
Jean-Marc Valin132ed592016-11-04 11:41:13 -04002168 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
Mark Harrisd74fa272016-11-05 21:32:28 -07002169 if (frame_size <= 0)
2170 {
2171 RESTORE_STACK;
2172 return OPUS_BAD_ARG;
2173 }
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002174 ALLOC(in, frame_size*st->channels, opus_int16);
2175
2176 for (i=0;i<frame_size*st->channels;i++)
2177 in[i] = FLOAT2INT16(pcm[i]);
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05002178 ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
2179 pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002180 RESTORE_STACK;
2181 return ret;
2182}
2183#endif
2184
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002185opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -05002186 unsigned char *data, opus_int32 out_data_bytes)
2187{
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002188 int frame_size;
Jean-Marc Valin132ed592016-11-04 11:41:13 -04002189 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05002190 return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16,
2191 pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
Jean-Marc Valinb3eba242012-12-20 23:11:53 -05002192}
2193
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002194#else
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002195opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
Gregory Maxwelle7028172011-11-19 23:58:09 -05002196 unsigned char *data, opus_int32 max_data_bytes)
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002197{
2198 int i, ret;
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002199 int frame_size;
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002200 VARDECL(float, in);
2201 ALLOC_STACK;
2202
Jean-Marc Valin132ed592016-11-04 11:41:13 -04002203 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
Mark Harrisd74fa272016-11-05 21:32:28 -07002204 if (frame_size <= 0)
2205 {
2206 RESTORE_STACK;
2207 return OPUS_BAD_ARG;
2208 }
Jean-Marc Valin6b9087a2013-09-28 23:51:11 -04002209 ALLOC(in, frame_size*st->channels, float);
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002210
Jean-Marc Valin6b9087a2013-09-28 23:51:11 -04002211 for (i=0;i<frame_size*st->channels;i++)
Koen Vos854fe702011-10-09 20:34:41 -04002212 in[i] = (1.0f/32768)*pcm[i];
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05002213 ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
2214 pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002215 RESTORE_STACK;
2216 return ret;
2217}
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002218opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -05002219 unsigned char *data, opus_int32 out_data_bytes)
2220{
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002221 int frame_size;
Jean-Marc Valin132ed592016-11-04 11:41:13 -04002222 frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
Jean-Marc Valinb90e63b2013-09-16 13:08:52 -04002223 return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24,
Jean-Marc Valinc94e4bb2013-12-08 03:31:50 -05002224 pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
Jean-Marc Valinb3eba242012-12-20 23:11:53 -05002225}
Jean-Marc Valin222494f2011-08-17 15:53:37 -04002226#endif
2227
2228
Jean-Marc Valin955f94c2011-03-08 22:12:43 -05002229int opus_encoder_ctl(OpusEncoder *st, int request, ...)
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002230{
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04002231 int ret;
Ralph Giles641eea82011-08-02 10:06:59 -07002232 CELTEncoder *celt_enc;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002233 va_list ap;
2234
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04002235 ret = OPUS_OK;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002236 va_start(ap, request);
2237
Jean-Marc Valin5095c472011-05-05 19:47:48 -04002238 celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
2239
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002240 switch (request)
2241 {
Jean-Marc Valin69549ac2011-08-18 17:28:28 -04002242 case OPUS_SET_APPLICATION_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002243 {
Ralph Giles04cca282011-08-24 00:29:29 -04002244 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -04002245 if ( (value != OPUS_APPLICATION_VOIP && value != OPUS_APPLICATION_AUDIO
2246 && value != OPUS_APPLICATION_RESTRICTED_LOWDELAY)
2247 || (!st->first && st->application != value))
2248 {
2249 ret = OPUS_BAD_ARG;
2250 break;
2251 }
Jean-Marc Valin69549ac2011-08-18 17:28:28 -04002252 st->application = value;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002253 }
2254 break;
Jean-Marc Valin69549ac2011-08-18 17:28:28 -04002255 case OPUS_GET_APPLICATION_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002256 {
Ralph Giles04cca282011-08-24 00:29:29 -04002257 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002258 if (!value)
2259 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002260 goto bad_arg;
2261 }
Gregory Maxwell220a7d42011-10-01 20:30:16 -04002262 *value = st->application;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002263 }
2264 break;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002265 case OPUS_SET_BITRATE_REQUEST:
2266 {
Ralph Giles04cca282011-08-24 00:29:29 -04002267 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04002268 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Jean-Marc Valinba547462011-05-10 17:54:41 -04002269 {
2270 if (value <= 0)
2271 goto bad_arg;
2272 else if (value <= 500)
2273 value = 500;
Jean-Marc Valin69f44c52011-09-07 02:43:23 -04002274 else if (value > (opus_int32)300000*st->channels)
2275 value = (opus_int32)300000*st->channels;
Jean-Marc Valinba547462011-05-10 17:54:41 -04002276 }
2277 st->user_bitrate_bps = value;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002278 }
2279 break;
2280 case OPUS_GET_BITRATE_REQUEST:
2281 {
Ralph Giles04cca282011-08-24 00:29:29 -04002282 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002283 if (!value)
2284 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002285 goto bad_arg;
2286 }
Gregory Maxwell220a7d42011-10-01 20:30:16 -04002287 *value = user_bitrate_to_bitrate(st, st->prev_framesize, 1276);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002288 }
2289 break;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04002290 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valin103302b2011-05-19 17:17:44 -04002291 {
Ralph Giles04cca282011-08-24 00:29:29 -04002292 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002293 if((value<1 || value>st->channels) && value != OPUS_AUTO)
2294 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002295 goto bad_arg;
2296 }
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04002297 st->force_channels = value;
Jean-Marc Valin103302b2011-05-19 17:17:44 -04002298 }
2299 break;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04002300 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valin103302b2011-05-19 17:17:44 -04002301 {
Ralph Giles04cca282011-08-24 00:29:29 -04002302 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002303 if (!value)
2304 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002305 goto bad_arg;
2306 }
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04002307 *value = st->force_channels;
Jean-Marc Valin103302b2011-05-19 17:17:44 -04002308 }
2309 break;
Jean-Marc Valin9ba17432011-10-24 22:41:18 -04002310 case OPUS_SET_MAX_BANDWIDTH_REQUEST:
2311 {
2312 opus_int32 value = va_arg(ap, opus_int32);
Timothy B. Terriberry554b3492014-10-03 21:49:57 -07002313 if (value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002314 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002315 goto bad_arg;
2316 }
Jean-Marc Valin9ba17432011-10-24 22:41:18 -04002317 st->max_bandwidth = value;
2318 if (st->max_bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
2319 st->silk_mode.maxInternalSampleRate = 8000;
2320 } else if (st->max_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
2321 st->silk_mode.maxInternalSampleRate = 12000;
2322 } else {
2323 st->silk_mode.maxInternalSampleRate = 16000;
2324 }
2325 }
2326 break;
2327 case OPUS_GET_MAX_BANDWIDTH_REQUEST:
2328 {
2329 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002330 if (!value)
2331 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002332 goto bad_arg;
2333 }
Jean-Marc Valin9ba17432011-10-24 22:41:18 -04002334 *value = st->max_bandwidth;
2335 }
2336 break;
Jean-Marc Valin05dd36a2010-10-18 12:50:49 -04002337 case OPUS_SET_BANDWIDTH_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002338 {
Ralph Giles04cca282011-08-24 00:29:29 -04002339 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002340 if ((value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) && value != OPUS_AUTO)
2341 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002342 goto bad_arg;
2343 }
Jean-Marc Valin955f94c2011-03-08 22:12:43 -05002344 st->user_bandwidth = value;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -04002345 if (st->user_bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002346 st->silk_mode.maxInternalSampleRate = 8000;
Gregory Maxwell87141892011-10-02 03:19:15 -04002347 } else if (st->user_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002348 st->silk_mode.maxInternalSampleRate = 12000;
2349 } else {
2350 st->silk_mode.maxInternalSampleRate = 16000;
2351 }
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002352 }
2353 break;
Jean-Marc Valin05dd36a2010-10-18 12:50:49 -04002354 case OPUS_GET_BANDWIDTH_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002355 {
Ralph Giles04cca282011-08-24 00:29:29 -04002356 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002357 if (!value)
2358 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002359 goto bad_arg;
2360 }
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002361 *value = st->bandwidth;
2362 }
2363 break;
Jean-Marc Valind4827732011-08-19 17:07:16 -04002364 case OPUS_SET_DTX_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002365 {
Ralph Giles04cca282011-08-24 00:29:29 -04002366 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002367 if(value<0 || value>1)
2368 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002369 goto bad_arg;
2370 }
Felicia Lim36481342016-05-16 15:29:53 +02002371 st->use_dtx = value;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002372 }
2373 break;
Jean-Marc Valind4827732011-08-19 17:07:16 -04002374 case OPUS_GET_DTX_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002375 {
Ralph Giles04cca282011-08-24 00:29:29 -04002376 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002377 if (!value)
2378 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002379 goto bad_arg;
2380 }
Felicia Lim36481342016-05-16 15:29:53 +02002381 *value = st->use_dtx;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002382 }
2383 break;
2384 case OPUS_SET_COMPLEXITY_REQUEST:
2385 {
Ralph Giles04cca282011-08-24 00:29:29 -04002386 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002387 if(value<0 || value>10)
2388 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002389 goto bad_arg;
2390 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002391 st->silk_mode.complexity = value;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002392 celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(value));
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002393 }
2394 break;
2395 case OPUS_GET_COMPLEXITY_REQUEST:
2396 {
Ralph Giles04cca282011-08-24 00:29:29 -04002397 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002398 if (!value)
2399 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002400 goto bad_arg;
2401 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002402 *value = st->silk_mode.complexity;
2403 }
2404 break;
Jean-Marc Valine766d9f2011-08-28 20:27:18 -04002405 case OPUS_SET_INBAND_FEC_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002406 {
Ralph Giles04cca282011-08-24 00:29:29 -04002407 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002408 if(value<0 || value>1)
2409 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002410 goto bad_arg;
2411 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002412 st->silk_mode.useInBandFEC = value;
2413 }
2414 break;
Jean-Marc Valine766d9f2011-08-28 20:27:18 -04002415 case OPUS_GET_INBAND_FEC_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002416 {
Ralph Giles04cca282011-08-24 00:29:29 -04002417 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002418 if (!value)
2419 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002420 goto bad_arg;
2421 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002422 *value = st->silk_mode.useInBandFEC;
2423 }
2424 break;
2425 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
2426 {
Ralph Giles04cca282011-08-24 00:29:29 -04002427 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002428 if (value < 0 || value > 100)
2429 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002430 goto bad_arg;
2431 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002432 st->silk_mode.packetLossPercentage = value;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002433 celt_encoder_ctl(celt_enc, OPUS_SET_PACKET_LOSS_PERC(value));
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002434 }
2435 break;
2436 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
2437 {
Ralph Giles04cca282011-08-24 00:29:29 -04002438 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002439 if (!value)
2440 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002441 goto bad_arg;
2442 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002443 *value = st->silk_mode.packetLossPercentage;
2444 }
2445 break;
Jean-Marc Valind7f67002011-08-18 16:55:24 -04002446 case OPUS_SET_VBR_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002447 {
Ralph Giles04cca282011-08-24 00:29:29 -04002448 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002449 if(value<0 || value>1)
2450 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002451 goto bad_arg;
2452 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002453 st->use_vbr = value;
2454 st->silk_mode.useCBR = 1-value;
2455 }
2456 break;
Jean-Marc Valind7f67002011-08-18 16:55:24 -04002457 case OPUS_GET_VBR_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002458 {
Ralph Giles04cca282011-08-24 00:29:29 -04002459 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002460 if (!value)
2461 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002462 goto bad_arg;
2463 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05002464 *value = st->use_vbr;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002465 }
2466 break;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05002467 case OPUS_SET_VOICE_RATIO_REQUEST:
2468 {
Ralph Giles04cca282011-08-24 00:29:29 -04002469 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002470 if (value<-1 || value>100)
2471 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002472 goto bad_arg;
2473 }
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05002474 st->voice_ratio = value;
2475 }
2476 break;
2477 case OPUS_GET_VOICE_RATIO_REQUEST:
2478 {
Ralph Giles04cca282011-08-24 00:29:29 -04002479 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002480 if (!value)
2481 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002482 goto bad_arg;
2483 }
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05002484 *value = st->voice_ratio;
2485 }
2486 break;
Jean-Marc Valinb55b6612011-03-14 15:11:44 -04002487 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
2488 {
Ralph Giles04cca282011-08-24 00:29:29 -04002489 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002490 if(value<0 || value>1)
2491 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002492 goto bad_arg;
2493 }
Jean-Marc Valinb55b6612011-03-14 15:11:44 -04002494 st->vbr_constraint = value;
2495 }
2496 break;
2497 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
2498 {
Ralph Giles04cca282011-08-24 00:29:29 -04002499 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002500 if (!value)
2501 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002502 goto bad_arg;
2503 }
Jean-Marc Valinb55b6612011-03-14 15:11:44 -04002504 *value = st->vbr_constraint;
2505 }
2506 break;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04002507 case OPUS_SET_SIGNAL_REQUEST:
2508 {
Ralph Giles04cca282011-08-24 00:29:29 -04002509 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002510 if(value!=OPUS_AUTO && value!=OPUS_SIGNAL_VOICE && value!=OPUS_SIGNAL_MUSIC)
2511 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002512 goto bad_arg;
2513 }
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04002514 st->signal_type = value;
2515 }
2516 break;
2517 case OPUS_GET_SIGNAL_REQUEST:
2518 {
Ralph Giles04cca282011-08-24 00:29:29 -04002519 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002520 if (!value)
2521 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002522 goto bad_arg;
2523 }
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04002524 *value = st->signal_type;
2525 }
2526 break;
Jean-Marc Valin9d8b5192011-08-03 12:44:37 -04002527 case OPUS_GET_LOOKAHEAD_REQUEST:
2528 {
Ralph Giles04cca282011-08-24 00:29:29 -04002529 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002530 if (!value)
2531 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002532 goto bad_arg;
2533 }
Jean-Marc Valind186c912011-09-08 15:13:46 -04002534 *value = st->Fs/400;
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -04002535 if (st->application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)
Koen Vos854fe702011-10-09 20:34:41 -04002536 *value += st->delay_compensation;
Jean-Marc Valin9d8b5192011-08-03 12:44:37 -04002537 }
2538 break;
Timothy B. Terriberrya40689e2012-09-07 06:01:53 -07002539 case OPUS_GET_SAMPLE_RATE_REQUEST:
2540 {
2541 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002542 if (!value)
2543 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002544 goto bad_arg;
2545 }
Timothy B. Terriberrya40689e2012-09-07 06:01:53 -07002546 *value = st->Fs;
2547 }
2548 break;
Jean-Marc Valind4827732011-08-19 17:07:16 -04002549 case OPUS_GET_FINAL_RANGE_REQUEST:
2550 {
2551 opus_uint32 *value = va_arg(ap, opus_uint32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002552 if (!value)
2553 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002554 goto bad_arg;
2555 }
Jean-Marc Valind4827732011-08-19 17:07:16 -04002556 *value = st->rangeFinal;
2557 }
2558 break;
Jean-Marc Valin1cd5d952012-07-11 02:54:47 -04002559 case OPUS_SET_LSB_DEPTH_REQUEST:
2560 {
2561 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002562 if (value<8 || value>24)
2563 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002564 goto bad_arg;
2565 }
Jean-Marc Valin7509fdb2012-12-20 22:48:35 -05002566 st->lsb_depth=value;
Jean-Marc Valin1cd5d952012-07-11 02:54:47 -04002567 }
2568 break;
2569 case OPUS_GET_LSB_DEPTH_REQUEST:
2570 {
2571 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002572 if (!value)
2573 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002574 goto bad_arg;
2575 }
Jean-Marc Valin7509fdb2012-12-20 22:48:35 -05002576 *value = st->lsb_depth;
Jean-Marc Valin1cd5d952012-07-11 02:54:47 -04002577 }
2578 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05002579 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin49583ed2012-11-22 13:11:43 -05002580 {
2581 opus_int32 value = va_arg(ap, opus_int32);
Felicia Lim0962cbe2016-10-27 17:03:36 -07002582 if (value != OPUS_FRAMESIZE_ARG && value != OPUS_FRAMESIZE_2_5_MS &&
2583 value != OPUS_FRAMESIZE_5_MS && value != OPUS_FRAMESIZE_10_MS &&
2584 value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS &&
2585 value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_80_MS &&
Jean-Marc Valin132ed592016-11-04 11:41:13 -04002586 value != OPUS_FRAMESIZE_100_MS && value != OPUS_FRAMESIZE_120_MS)
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002587 {
2588 goto bad_arg;
Gregory Maxwelldd7b0da2013-06-29 20:06:07 -07002589 }
Jean-Marc Valin49583ed2012-11-22 13:11:43 -05002590 st->variable_duration = value;
Jean-Marc Valin3252bf22013-04-19 03:14:28 -04002591 celt_encoder_ctl(celt_enc, OPUS_SET_EXPERT_FRAME_DURATION(value));
Jean-Marc Valin49583ed2012-11-22 13:11:43 -05002592 }
2593 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05002594 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin49583ed2012-11-22 13:11:43 -05002595 {
2596 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002597 if (!value)
2598 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002599 goto bad_arg;
2600 }
Jean-Marc Valin49583ed2012-11-22 13:11:43 -05002601 *value = st->variable_duration;
2602 }
2603 break;
Jean-Marc Valincbe93e22013-11-15 13:50:38 -05002604 case OPUS_SET_PREDICTION_DISABLED_REQUEST:
2605 {
2606 opus_int32 value = va_arg(ap, opus_int32);
2607 if (value > 1 || value < 0)
2608 goto bad_arg;
2609 st->silk_mode.reducedDependency = value;
2610 }
2611 break;
2612 case OPUS_GET_PREDICTION_DISABLED_REQUEST:
2613 {
2614 opus_int32 *value = va_arg(ap, opus_int32*);
2615 if (!value)
2616 goto bad_arg;
2617 *value = st->silk_mode.reducedDependency;
2618 }
2619 break;
Jean-Marc Valin18a380a2016-04-20 13:27:06 -04002620 case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
2621 {
2622 opus_int32 value = va_arg(ap, opus_int32);
2623 if(value<0 || value>1)
2624 {
2625 goto bad_arg;
2626 }
2627 celt_encoder_ctl(celt_enc, OPUS_SET_PHASE_INVERSION_DISABLED(value));
2628 }
2629 break;
2630 case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
2631 {
2632 opus_int32 *value = va_arg(ap, opus_int32*);
2633 if (!value)
2634 {
2635 goto bad_arg;
2636 }
2637 celt_encoder_ctl(celt_enc, OPUS_GET_PHASE_INVERSION_DISABLED(value));
2638 }
2639 break;
Jean-Marc Valin927488b2011-08-30 20:09:22 -04002640 case OPUS_RESET_STATE:
2641 {
2642 void *silk_enc;
2643 silk_EncControlStruct dummy;
Timothy B. Terriberrydd6dec92015-12-31 05:00:31 -08002644 char *start;
Timothy B. Terriberry9ba205d2015-12-31 05:56:45 -08002645 silk_enc = (char*)st+st->silk_enc_offset;
Ralph Giles9e3872a2015-12-30 15:27:02 -08002646#ifndef DISABLE_FLOAT_API
2647 tonality_analysis_reset(&st->analysis);
2648#endif
Jean-Marc Valin927488b2011-08-30 20:09:22 -04002649
Timothy B. Terriberrydd6dec92015-12-31 05:00:31 -08002650 start = (char*)&st->OPUS_ENCODER_RESET_START;
Ralph Giles9e3872a2015-12-30 15:27:02 -08002651 OPUS_CLEAR(start, sizeof(OpusEncoder) - (start - (char*)st));
Jean-Marc Valin927488b2011-08-30 20:09:22 -04002652
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04002653 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
Timothy B. Terriberry39386e02013-11-18 13:30:13 -05002654 silk_InitEncoder( silk_enc, st->arch, &dummy );
Jean-Marc Valin927488b2011-08-30 20:09:22 -04002655 st->stream_channels = st->channels;
Koen Vos854fe702011-10-09 20:34:41 -04002656 st->hybrid_stereo_width_Q14 = 1 << 14;
Jean-Marc Valinf68799b2012-07-12 17:36:11 -04002657 st->prev_HB_gain = Q15ONE;
Jean-Marc Valin927488b2011-08-30 20:09:22 -04002658 st->first = 1;
2659 st->mode = MODE_HYBRID;
2660 st->bandwidth = OPUS_BANDWIDTH_FULLBAND;
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -07002661 st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
Jean-Marc Valin927488b2011-08-30 20:09:22 -04002662 }
2663 break;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04002664 case OPUS_SET_FORCE_MODE_REQUEST:
2665 {
2666 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002667 if ((value < MODE_SILK_ONLY || value > MODE_CELT_ONLY) && value != OPUS_AUTO)
2668 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002669 goto bad_arg;
2670 }
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04002671 st->user_forced_mode = value;
2672 }
2673 break;
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -04002674 case OPUS_SET_LFE_REQUEST:
2675 {
2676 opus_int32 value = va_arg(ap, opus_int32);
2677 st->lfe = value;
Gregory Maxwelldd7b0da2013-06-29 20:06:07 -07002678 ret = celt_encoder_ctl(celt_enc, OPUS_SET_LFE(value));
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -04002679 }
2680 break;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04002681 case OPUS_SET_ENERGY_MASK_REQUEST:
2682 {
2683 opus_val16 *value = va_arg(ap, opus_val16*);
Jean-Marc Valin8824fdb2013-09-10 01:15:19 -04002684 st->energy_masking = value;
Gregory Maxwelldd7b0da2013-06-29 20:06:07 -07002685 ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -04002686 }
2687 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05002688
2689 case CELT_GET_MODE_REQUEST:
2690 {
2691 const CELTMode ** value = va_arg(ap, const CELTMode**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07002692 if (!value)
2693 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07002694 goto bad_arg;
2695 }
Gregory Maxwelldd7b0da2013-06-29 20:06:07 -07002696 ret = celt_encoder_ctl(celt_enc, CELT_GET_MODE(value));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05002697 }
2698 break;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002699 default:
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04002700 /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/
Jean-Marc Valin06237d72011-09-01 13:20:40 -04002701 ret = OPUS_UNIMPLEMENTED;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04002702 break;
Jean-Marc Valinc5ea0742010-07-05 11:11:54 -04002703 }
Alfred E. Heggestad3d31d702010-07-27 16:38:04 +02002704 va_end(ap);
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04002705 return ret;
Jean-Marc Valind2124cd2011-04-25 13:36:14 -04002706bad_arg:
2707 va_end(ap);
2708 return OPUS_BAD_ARG;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04002709}
2710
Jean-Marc Valin05dd36a2010-10-18 12:50:49 -04002711void opus_encoder_destroy(OpusEncoder *st)
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04002712{
Jean-Marc Valin07f88402011-08-29 15:08:51 -04002713 opus_free(st);
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04002714}