blob: 156412cf744c027f6f74e08c78516a280d40208d [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
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
19 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 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 Valin6696a142011-08-22 10:40:38 -040041#include "opus_private.h"
Jean-Marc Valin07f88402011-08-29 15:08:51 -040042#include "os_support.h"
Jean-Marc Valin222494f2011-08-17 15:53:37 -040043
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070044#include "tuning_parameters.h"
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040045#ifdef FIXED_POINT
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070046#include "fixed/structs_FIX.h"
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040047#else
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070048#include "float/structs_FLP.h"
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040049#endif
50
Jean-Marc Valind9920f32011-08-19 13:00:49 -040051#define MAX_ENCODER_BUFFER 480
52
53struct OpusEncoder {
54 int celt_enc_offset;
55 int silk_enc_offset;
56 silk_EncControlStruct silk_mode;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040057 int application;
Jean-Marc Valin927488b2011-08-30 20:09:22 -040058 int channels;
59 int delay_compensation;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -040060 int force_channels;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040061 int signal_type;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040062 int user_bandwidth;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -040063 int user_forced_mode;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040064 int voice_ratio;
Gregory Maxwell64a35412011-09-02 10:31:17 -040065 opus_int32 Fs;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040066 int use_vbr;
67 int vbr_constraint;
Jean-Marc Valin8fdf2af2011-09-10 21:56:34 -040068 opus_int32 bitrate_bps;
69 opus_int32 user_bitrate_bps;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040070 int encoder_buffer;
Jean-Marc Valin927488b2011-08-30 20:09:22 -040071
72#define OPUS_ENCODER_RESET_START stream_channels
73 int stream_channels;
Jean-Marc Valin8fdf2af2011-09-10 21:56:34 -040074 opus_int16 hybrid_stereo_width_Q14;
Jean-Marc Valin957f7f12011-09-01 18:02:43 -040075 opus_int32 variable_HP_smth2_Q15;
76 opus_val32 hp_mem[4];
Jean-Marc Valin927488b2011-08-30 20:09:22 -040077 int mode;
78 int prev_mode;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -040079 int prev_channels;
Gregory Maxwell220a7d42011-10-01 20:30:16 -040080 int prev_framesize;
Jean-Marc Valin927488b2011-08-30 20:09:22 -040081 int bandwidth;
82 /* Sampling rate (at the API level) */
Jean-Marc Valind9920f32011-08-19 13:00:49 -040083 int first;
84 opus_val16 delay_buffer[MAX_ENCODER_BUFFER*2];
85
Gregory Maxwell64a35412011-09-02 10:31:17 -040086 opus_uint32 rangeFinal;
Jean-Marc Valind9920f32011-08-19 13:00:49 -040087};
88
Jean-Marc Valinc681bd02011-09-02 14:47:26 -040089/* Transition tables for the voice and music. First column is the
Jean-Marc Valin9edde422011-05-05 15:30:44 -040090 middle (memoriless) threshold. The second column is the hysteresis
91 (difference with the middle) */
Jean-Marc Valinc681bd02011-09-02 14:47:26 -040092static const opus_int32 mono_voice_bandwidth_thresholds[8] = {
Ralph Giles04cca282011-08-24 00:29:29 -040093 11000, 1000, /* NB<->MB */
94 14000, 1000, /* MB<->WB */
95 21000, 2000, /* WB<->SWB */
96 29000, 2000, /* SWB<->FB */
Jean-Marc Valin09c67662011-05-04 22:34:53 -040097};
Jean-Marc Valinc681bd02011-09-02 14:47:26 -040098static const opus_int32 mono_music_bandwidth_thresholds[8] = {
99 14000, 1000, /* MB not allowed */
100 18000, 2000, /* MB<->WB */
101 24000, 2000, /* WB<->SWB */
Ralph Giles04cca282011-08-24 00:29:29 -0400102 33000, 2000, /* SWB<->FB */
Jean-Marc Valin09c67662011-05-04 22:34:53 -0400103};
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400104static const opus_int32 stereo_voice_bandwidth_thresholds[8] = {
105 11000, 1000, /* NB<->MB */
106 14000, 1000, /* MB<->WB */
107 21000, 2000, /* WB<->SWB */
108 32000, 2000, /* SWB<->FB */
109};
110static const opus_int32 stereo_music_bandwidth_thresholds[8] = {
111 14000, 1000, /* MB not allowed */
112 18000, 2000, /* MB<->WB */
113 24000, 2000, /* WB<->SWB */
114 48000, 2000, /* SWB<->FB */
115};
116/* Threshold bit-rates for switching between mono and stereo */
117static const opus_int32 stereo_voice_threshold = 26000;
118static const opus_int32 stereo_music_threshold = 36000;
Jean-Marc Valin09c67662011-05-04 22:34:53 -0400119
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400120/* Threshold bit-rate for switching between SILK/hybrid and CELT-only */
121static const opus_int32 mode_thresholds[2][2] = {
122 /* voice */ /* music */
123 { 48000, 24000}, /* mono */
124 { 48000, 24000}, /* stereo */
125};
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400126int opus_encoder_get_size(int channels)
127{
Ralph Giles641eea82011-08-02 10:06:59 -0700128 int silkEncSizeBytes, celtEncSizeBytes;
129 int ret;
Gregory Maxwellf451b332011-09-04 10:47:15 -0400130 if (channels<1 || channels > 2)
131 return 0;
Ralph Giles641eea82011-08-02 10:06:59 -0700132 ret = silk_Get_Encoder_Size( &silkEncSizeBytes );
Ralph Giles04cca282011-08-24 00:29:29 -0400133 if (ret)
Ralph Giles641eea82011-08-02 10:06:59 -0700134 return 0;
135 silkEncSizeBytes = align(silkEncSizeBytes);
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400136 celtEncSizeBytes = celt_encoder_get_size(channels);
137 return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes;
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400138}
139
Gregory Maxwell64a35412011-09-02 10:31:17 -0400140int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int application)
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400141{
Ralph Giles641eea82011-08-02 10:06:59 -0700142 void *silk_enc;
143 CELTEncoder *celt_enc;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500144 int err;
Ralph Giles641eea82011-08-02 10:06:59 -0700145 int ret, silkEncSizeBytes;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400146
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400147 if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)||
148 (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO
149 && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY))
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400150 return OPUS_BAD_ARG;
Jean-Marc Valind3358b12011-06-14 14:48:53 -0400151
Jean-Marc Valinbe89c392011-08-30 12:39:51 -0400152 OPUS_CLEAR((char*)st, opus_encoder_get_size(channels));
Jean-Marc Valind3358b12011-06-14 14:48:53 -0400153 /* Create SILK encoder */
154 ret = silk_Get_Encoder_Size( &silkEncSizeBytes );
Ralph Giles04cca282011-08-24 00:29:29 -0400155 if (ret)
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400156 return OPUS_BAD_ARG;
Ralph Giles04cca282011-08-24 00:29:29 -0400157 silkEncSizeBytes = align(silkEncSizeBytes);
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400158 st->silk_enc_offset = align(sizeof(OpusEncoder));
159 st->celt_enc_offset = st->silk_enc_offset+silkEncSizeBytes;
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400160 silk_enc = (char*)st+st->silk_enc_offset;
161 celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
162
Jean-Marc Valinb3864582011-01-31 12:41:49 -0500163 st->stream_channels = st->channels = channels;
Jean-Marc Valinbcdfe632010-08-31 11:22:43 -0400164
165 st->Fs = Fs;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400166
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400167 ret = silk_InitEncoder( silk_enc, &st->silk_mode );
Gregory Maxwelle03af442011-09-04 04:43:11 -0400168 if(ret)return OPUS_INTERNAL_ERROR;
Jean-Marc Valinae180902010-07-19 11:44:36 -0400169
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500170 /* default SILK parameters */
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400171 st->silk_mode.nChannelsAPI = channels;
172 st->silk_mode.nChannelsInternal = channels;
173 st->silk_mode.API_sampleRate = st->Fs;
174 st->silk_mode.maxInternalSampleRate = 16000;
175 st->silk_mode.minInternalSampleRate = 8000;
176 st->silk_mode.desiredInternalSampleRate = 16000;
177 st->silk_mode.payloadSize_ms = 20;
178 st->silk_mode.bitRate = 25000;
179 st->silk_mode.packetLossPercentage = 0;
180 st->silk_mode.complexity = 10;
181 st->silk_mode.useInBandFEC = 0;
182 st->silk_mode.useDTX = 0;
183 st->silk_mode.useCBR = 0;
184
Jean-Marc Valinc5ea0742010-07-05 11:11:54 -0400185 /* Create CELT encoder */
Ralph Giles641eea82011-08-02 10:06:59 -0700186 /* Initialize CELT encoder */
Jean-Marc Valin875f8db2011-08-31 16:43:08 -0400187 err = celt_encoder_init(celt_enc, Fs, channels);
Gregory Maxwelle03af442011-09-04 04:43:11 -0400188 if(err!=OPUS_OK)return OPUS_INTERNAL_ERROR;
189
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400190 celt_encoder_ctl(celt_enc, CELT_SET_SIGNALLING(0));
Jean-Marc Valincdfb8f32011-09-09 14:50:15 -0400191 celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(10));
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400192
Jean-Marc Valin21452882011-09-09 14:57:43 -0400193 st->use_vbr = 1;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400194 st->user_bitrate_bps = OPUS_AUTO;
Ralph Giles641eea82011-08-02 10:06:59 -0700195 st->bitrate_bps = 3000+Fs*channels;
Jean-Marc Valin69549ac2011-08-18 17:28:28 -0400196 st->application = application;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400197 st->signal_type = OPUS_AUTO;
198 st->user_bandwidth = OPUS_AUTO;
199 st->force_channels = OPUS_AUTO;
200 st->user_forced_mode = OPUS_AUTO;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400201 st->voice_ratio = -1;
Ralph Giles641eea82011-08-02 10:06:59 -0700202 st->encoder_buffer = st->Fs/100;
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400203
Ralph Giles641eea82011-08-02 10:06:59 -0700204 st->delay_compensation = st->Fs/400;
Jean-Marc Valin073c4e12011-08-26 13:01:42 -0400205 /* This part is meant to compensate for the resampler delay as a function
206 of the API sampling rate */
207 if (st->Fs == 48000)
208 st->delay_compensation += 23;
209 else if (st->Fs == 24000)
210 st->delay_compensation += 15;
211 else
212 st->delay_compensation += 2;
213
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400214 st->hybrid_stereo_width_Q14 = 1 << 14;
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700215 st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
Jean-Marc Valin927488b2011-08-30 20:09:22 -0400216 st->first = 1;
217 st->mode = MODE_HYBRID;
218 st->bandwidth = OPUS_BANDWIDTH_FULLBAND;
219
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400220 return OPUS_OK;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400221}
222
Jean-Marc Valin69bfc672011-08-29 21:46:17 -0400223static unsigned char gen_toc(int mode, int framerate, int bandwidth, int silk_bandwidth, int channels)
Jean-Marc Valin421a6282011-08-18 14:32:16 -0400224{
225 int period;
226 unsigned char toc;
227 period = 0;
228 while (framerate < 400)
229 {
230 framerate <<= 1;
231 period++;
232 }
233 if (mode == MODE_SILK_ONLY)
234 {
Jean-Marc Valin69bfc672011-08-29 21:46:17 -0400235 toc = (silk_bandwidth-OPUS_BANDWIDTH_NARROWBAND)<<5;
Jean-Marc Valin421a6282011-08-18 14:32:16 -0400236 toc |= (period-2)<<3;
237 } else if (mode == MODE_CELT_ONLY)
238 {
239 int tmp = bandwidth-OPUS_BANDWIDTH_MEDIUMBAND;
240 if (tmp < 0)
241 tmp = 0;
242 toc = 0x80;
243 toc |= tmp << 5;
244 toc |= period<<3;
245 } else /* Hybrid */
246 {
247 toc = 0x60;
248 toc |= (bandwidth-OPUS_BANDWIDTH_SUPERWIDEBAND)<<4;
249 toc |= (period-2)<<3;
250 }
251 toc |= (channels==2)<<2;
252 return toc;
253}
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400254
255#ifndef FIXED_POINT
256void silk_biquad_float(
257 const opus_val16 *in, /* I: Input signal */
258 const opus_int32 *B_Q28, /* I: MA coefficients [3] */
259 const opus_int32 *A_Q28, /* I: AR coefficients [2] */
260 opus_val32 *S, /* I/O: State vector [2] */
261 opus_val16 *out, /* O: Output signal */
262 const opus_int32 len, /* I: Signal length (must be even) */
263 int stride
264)
265{
266 /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
267 opus_int k;
268 opus_val32 vout;
269 opus_val32 inval;
270 opus_val32 A[2], B[3];
271
272 A[0] = A_Q28[0] * (1./((opus_int32)1<<28));
273 A[1] = A_Q28[1] * (1./((opus_int32)1<<28));
274 B[0] = B_Q28[0] * (1./((opus_int32)1<<28));
275 B[1] = B_Q28[1] * (1./((opus_int32)1<<28));
276 B[2] = B_Q28[2] * (1./((opus_int32)1<<28));
277
278 /* Negate A_Q28 values and split in two parts */
279
280 for( k = 0; k < len; k++ ) {
281 /* S[ 0 ], S[ 1 ]: Q12 */
282 inval = in[ k*stride ];
283 vout = S[ 0 ] + B[0]*inval;
284
285 S[ 0 ] = S[1] - vout*A[0] + B[1]*inval;
286
287 S[ 1 ] = - vout*A[1] + B[2]*inval;
288
289 /* Scale back to Q0 and saturate */
290 out[ k*stride ] = vout;
291 }
292}
293#endif
294
295static 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)
296{
297 opus_int32 B_Q28[ 3 ], A_Q28[ 2 ];
298 opus_int32 Fc_Q19, r_Q28, r_Q22;
299
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700300 silk_assert( cutoff_Hz <= silk_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) );
301 Fc_Q19 = silk_DIV32_16( silk_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), Fs/1000 );
302 silk_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400303
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700304 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 -0400305
306 /* b = r * [ 1; -2; 1 ]; */
307 /* a = [ 1; -2 * r * ( 1 - 0.5 * Fc^2 ); r^2 ]; */
308 B_Q28[ 0 ] = r_Q28;
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700309 B_Q28[ 1 ] = silk_LSHIFT( -r_Q28, 1 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400310 B_Q28[ 2 ] = r_Q28;
311
312 /* -r * ( 2 - Fc * Fc ); */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700313 r_Q22 = silk_RSHIFT( r_Q28, 6 );
314 A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0, 22 ) );
315 A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400316
317#ifdef FIXED_POINT
318 silk_biquad_alt( in, B_Q28, A_Q28, hp_mem, out, len, channels );
319 if( channels == 2 ) {
320 silk_biquad_alt( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
321 }
322#else
323 silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels );
324 if( channels == 2 ) {
325 silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
326 }
327#endif
328}
329
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400330static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2,
331 int overlap, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs)
332{
333 int i;
334 int inc = 48000/Fs;
335 g1 = Q15ONE-g1;
336 g2 = Q15ONE-g2;
337 for (i=0;i<overlap;i++)
338 {
339 opus_val32 diff;
340 opus_val16 g, w;
341 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
342 g = SHR32(MAC16_16(MULT16_16(w,g2),
343 Q15ONE-w, g1), 15);
344 diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]));
345 diff = MULT16_16_Q15(g, diff);
346 out[i*channels] = out[i*channels] - diff;
347 out[i*channels+1] = out[i*channels+1] + diff;
348 }
349 for (;i<frame_size;i++)
350 {
351 opus_val32 diff;
352 diff = EXTRACT16(HALF32((opus_val32)in[i*channels] - (opus_val32)in[i*channels+1]));
353 diff = MULT16_16_Q15(g2, diff);
354 out[i*channels] = out[i*channels] - diff;
355 out[i*channels+1] = out[i*channels+1] + diff;
356 }
357}
358
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400359OpusEncoder *opus_encoder_create(opus_int32 Fs, int channels, int application, int *error)
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400360{
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400361 int ret;
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400362 if((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)||(channels!=1&&channels!=2)||
363 (application != OPUS_APPLICATION_VOIP && application != OPUS_APPLICATION_AUDIO
364 && application != OPUS_APPLICATION_RESTRICTED_LOWDELAY))
365 {
366 if (error)
367 *error = OPUS_BAD_ARG;
368 return NULL;
369 }
Jean-Marc Valin85b8e622011-08-29 16:10:08 -0400370 OpusEncoder *st = (OpusEncoder *)opus_alloc(opus_encoder_get_size(channels));
371 if (st == NULL)
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400372 {
373 if (error)
374 *error = OPUS_ALLOC_FAIL;
375 return NULL;
376 }
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400377 ret = opus_encoder_init(st, Fs, channels, application);
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400378 if (error)
379 *error = ret;
380 if (ret != OPUS_OK)
381 {
Jean-Marc Valin85b8e622011-08-29 16:10:08 -0400382 opus_free(st);
383 st = NULL;
Jean-Marc Valin9d8dc3a2011-08-29 09:40:57 -0400384 }
Jean-Marc Valin85b8e622011-08-29 16:10:08 -0400385 return st;
Jean-Marc Valin280c0602011-05-05 20:47:42 -0400386}
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400387
388static opus_int32 user_bitrate_to_bitrate(OpusEncoder *st, int frame_size, int max_data_bytes)
389{
390 if(!frame_size)frame_size=st->Fs/400;
391 if (st->user_bitrate_bps==OPUS_AUTO)
392 return 60*st->Fs/frame_size + st->Fs*st->channels;
393 else if (st->user_bitrate_bps==OPUS_BITRATE_MAX)
394 return max_data_bytes*8*st->Fs/frame_size;
395 else
396 return st->user_bitrate_bps;
397}
398
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400399#ifdef FIXED_POINT
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400400#define opus_encode_native opus_encode
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400401int opus_encode(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
Ralph Giles04cca282011-08-24 00:29:29 -0400402 unsigned char *data, int max_data_bytes)
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400403#else
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400404#define opus_encode_native opus_encode_float
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400405int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
Ralph Giles04cca282011-08-24 00:29:29 -0400406 unsigned char *data, int max_data_bytes)
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400407#endif
Jean-Marc Valin3e66e912010-06-30 14:16:14 -0400408{
Ralph Giles641eea82011-08-02 10:06:59 -0700409 void *silk_enc;
410 CELTEncoder *celt_enc;
Jean-Marc Valine2d1ef12010-07-06 15:39:19 -0400411 int i;
Ralph Giles641eea82011-08-02 10:06:59 -0700412 int ret=0;
413 int nBytes;
414 ec_enc enc;
Jean-Marc Valin69bfc672011-08-29 21:46:17 -0400415 int silk_internal_bandwidth=-1;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500416 int bytes_target;
Jean-Marc Valine3de5052011-02-20 12:23:48 -0500417 int prefill=0;
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500418 int start_band = 0;
Jean-Marc Valine2a09db2011-03-02 17:54:43 -0500419 int redundancy = 0;
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500420 int redundancy_bytes = 0;
421 int celt_to_silk = 0;
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400422 VARDECL(opus_val16, pcm_buf);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500423 int nb_compr_bytes;
424 int to_celt = 0;
Jean-Marc Valin06cee2b2011-08-19 16:11:41 -0400425 opus_uint32 redundant_rng = 0;
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400426 int cutoff_Hz, hp_freq_smth1;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400427 int voice_est;
428 opus_int32 equiv_rate;
Jean-Marc Valind186c912011-09-08 15:13:46 -0400429 int delay_compensation;
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400430 ALLOC_STACK;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500431
Jean-Marc Valin904e7a82011-09-11 14:29:46 -0400432 max_data_bytes = IMIN(1276, max_data_bytes);
433
Jean-Marc Valin2b98bdf2011-08-20 00:21:46 -0400434 st->rangeFinal = 0;
Jean-Marc Valin23a900c2011-06-14 14:34:02 -0400435 if (400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
436 50*frame_size != st->Fs && 25*frame_size != st->Fs && 50*frame_size != 3*st->Fs)
Jean-Marc Valin44e27dd2011-08-29 23:35:17 -0400437 {
438 RESTORE_STACK;
439 return OPUS_BAD_ARG;
440 }
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400441 silk_enc = (char*)st+st->silk_enc_offset;
442 celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
Jean-Marc Valinba547462011-05-10 17:54:41 -0400443
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -0400444 if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
Jean-Marc Valind186c912011-09-08 15:13:46 -0400445 delay_compensation = 0;
446 else
447 delay_compensation = st->delay_compensation;
448
Gregory Maxwell220a7d42011-10-01 20:30:16 -0400449 st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
Jean-Marc Valinba547462011-05-10 17:54:41 -0400450
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400451 /* Equivalent 20-ms rate for mode/channel/bandwidth decisions */
452 equiv_rate = st->bitrate_bps - 60*(st->Fs/frame_size - 50);
453
454 if (st->signal_type == OPUS_SIGNAL_VOICE)
455 voice_est = 127;
456 else if (st->signal_type == OPUS_SIGNAL_MUSIC)
457 voice_est = 0;
458 else if (st->voice_ratio >= 0)
459 voice_est = st->voice_ratio*327>>8;
460 else if (st->application == OPUS_APPLICATION_VOIP)
461 voice_est = 115;
462 else
463 voice_est = 64;
464
465#ifdef FUZZING
466 /* Random mono/stereo decision */
467 if (st->channels == 2 && (rand()&0x1F)==0)
468 st->stream_channels = 3-st->stream_channels;
469#else
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400470 /* Rate-dependent mono-stereo decision */
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400471 if (st->force_channels!=OPUS_AUTO && st->channels == 2)
Koen Vos479e18b2011-05-25 23:09:52 -0400472 {
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400473 st->stream_channels = st->force_channels;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400474 } else if (st->channels == 2)
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500475 {
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400476 opus_int32 stereo_threshold;
477 stereo_threshold = stereo_music_threshold + ((voice_est*voice_est*(stereo_voice_threshold-stereo_music_threshold))>>14);
478 if (st->stream_channels == 2)
479 stereo_threshold -= 4000;
480 else
481 stereo_threshold += 4000;
482 st->stream_channels = (equiv_rate > stereo_threshold) ? 2 : 1;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500483 } else {
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400484 st->stream_channels = st->channels;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500485 }
Jean-Marc Valinf334c822011-08-11 16:21:58 -0400486#endif
487
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400488 if (st->silk_mode.toMono==1 && st->stream_channels==2)
489 {
490 /* In case the encoder changes its mind on stereo->mono transition */
491 st->silk_mode.toMono = -1;
Jean-Marc Valin1e0805d2011-10-03 13:52:18 -0400492 } else if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0)
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400493 {
Jean-Marc Valin1e0805d2011-10-03 13:52:18 -0400494 /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400495 st->silk_mode.toMono=1;
496 st->stream_channels = 2;
Jean-Marc Valin1e0805d2011-10-03 13:52:18 -0400497 } else if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==1)
498 {
499 st->silk_mode.toMono=2;
500 st->stream_channels = 2;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400501 } else {
502 st->silk_mode.toMono=0;
503 }
504
Jean-Marc Valinf334c822011-08-11 16:21:58 -0400505#ifdef FUZZING
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400506 /* Random mode switching */
Jean-Marc Valinf334c822011-08-11 16:21:58 -0400507 if ((rand()&0xF)==0)
508 {
509 if ((rand()&0x1)==0)
510 st->mode = MODE_CELT_ONLY;
511 else
512 st->mode = MODE_SILK_ONLY;
513 } else {
514 if (st->prev_mode==MODE_CELT_ONLY)
515 st->mode = MODE_CELT_ONLY;
516 else
517 st->mode = MODE_SILK_ONLY;
518 }
519#else
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -0400520 /* Mode selection depending on application and signal type */
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -0400521 if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
Jean-Marc Valind186c912011-09-08 15:13:46 -0400522 {
523 st->mode = MODE_CELT_ONLY;
524 } else if (st->user_forced_mode == OPUS_AUTO)
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500525 {
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400526 int chan;
527 opus_int32 mode_voice, mode_music;
528 opus_int32 threshold;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500529
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400530 chan = (st->channels==2) && st->force_channels!=1;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400531 mode_voice = mode_thresholds[chan][0];
532 mode_music = mode_thresholds[chan][1];
533 threshold = mode_music + ((voice_est*voice_est*(mode_voice-mode_music))>>14);
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -0400534
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400535 /* Hysteresis */
536 if (st->prev_mode == MODE_CELT_ONLY)
537 threshold -= 4000;
538 else if (st->prev_mode>0)
539 threshold += 4000;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -0400540
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400541 st->mode = (equiv_rate >= threshold) ? MODE_CELT_ONLY: MODE_SILK_ONLY;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400542 } else {
543 st->mode = st->user_forced_mode;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -0400544 }
Jean-Marc Valinf334c822011-08-11 16:21:58 -0400545#endif
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400546
Jean-Marc Valin81936d52011-08-13 01:44:39 -0400547 /* Override the chosen mode to make sure we meet the requested frame size */
Jean-Marc Valin81936d52011-08-13 01:44:39 -0400548 if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100)
549 st->mode = MODE_CELT_ONLY;
550
Jean-Marc Valin68545562011-08-12 00:30:47 -0400551 if (st->prev_mode > 0 &&
552 ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ||
553 (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)))
554 {
555 redundancy = 1;
556 celt_to_silk = (st->mode != MODE_CELT_ONLY);
557 if (!celt_to_silk)
558 {
559 /* Switch to SILK/hybrid if frame size is 10 ms or more*/
560 if (frame_size >= st->Fs/100)
561 {
562 st->mode = st->prev_mode;
563 to_celt = 1;
564 } else {
565 redundancy=0;
566 }
567 }
568 }
569 if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
570 {
571 silk_EncControlStruct dummy;
572 silk_InitEncoder( silk_enc, &dummy);
573 prefill=1;
574 }
575
Jean-Marc Valin243ff0c2011-05-03 17:06:54 -0400576 /* Automatic (rate-dependent) bandwidth selection */
Jean-Marc Valin09c67662011-05-04 22:34:53 -0400577 if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch)
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500578 {
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400579 const opus_int32 *voice_bandwidth_thresholds, *music_bandwidth_thresholds;
580 opus_int32 bandwidth_thresholds[8];
Ralph Giles641eea82011-08-02 10:06:59 -0700581 int bandwidth = OPUS_BANDWIDTH_FULLBAND;
Jean-Marc Valin09c67662011-05-04 22:34:53 -0400582
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400583 if (st->channels==2 && st->force_channels!=1)
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400584 {
585 voice_bandwidth_thresholds = stereo_voice_bandwidth_thresholds;
586 music_bandwidth_thresholds = stereo_music_bandwidth_thresholds;
587 } else {
588 voice_bandwidth_thresholds = mono_voice_bandwidth_thresholds;
589 music_bandwidth_thresholds = mono_music_bandwidth_thresholds;
590 }
591 /* Interpolate bandwidth thresholds depending on voice estimation */
592 for (i=0;i<8;i++)
593 {
594 bandwidth_thresholds[i] = music_bandwidth_thresholds[i]
595 + ((voice_est*voice_est*(voice_bandwidth_thresholds[i]-music_bandwidth_thresholds[i]))>>14);
596 }
Ralph Giles641eea82011-08-02 10:06:59 -0700597 do {
598 int threshold, hysteresis;
599 threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)];
600 hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1];
601 if (!st->first)
602 {
603 if (st->bandwidth >= bandwidth)
604 threshold -= hysteresis;
605 else
606 threshold += hysteresis;
607 }
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400608 if (equiv_rate >= threshold)
Ralph Giles641eea82011-08-02 10:06:59 -0700609 break;
610 } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND);
611 st->bandwidth = bandwidth;
612 /* Prevents any transition to SWB/FB until the SILK layer has fully
613 switched to WB mode and turned the variable LP filter off */
614 if (st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
615 st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500616 }
Jean-Marc Valin955f94c2011-03-08 22:12:43 -0500617
Jean-Marc Valinefe16c52011-09-29 22:02:37 -0400618 if (st->user_bandwidth != OPUS_AUTO)
619 st->bandwidth = st->user_bandwidth;
620
Jean-Marc Valin243ff0c2011-05-03 17:06:54 -0400621 /* Prevents Opus from wasting bits on frequencies that are above
622 the Nyquist rate of the input signal */
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400623 if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND)
Ralph Giles641eea82011-08-02 10:06:59 -0700624 st->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400625 if (st->Fs <= 16000 && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
Ralph Giles641eea82011-08-02 10:06:59 -0700626 st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400627 if (st->Fs <= 12000 && st->bandwidth > OPUS_BANDWIDTH_MEDIUMBAND)
Ralph Giles641eea82011-08-02 10:06:59 -0700628 st->bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400629 if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND)
Ralph Giles641eea82011-08-02 10:06:59 -0700630 st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
Jean-Marc Valin955f94c2011-03-08 22:12:43 -0500631
Jean-Marc Valin955f94c2011-03-08 22:12:43 -0500632
Jean-Marc Valin81936d52011-08-13 01:44:39 -0400633 /* Can't support higher than wideband for >20 ms frames */
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400634 if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
635 {
Jean-Marc Valind970a852011-09-08 21:41:29 -0400636 VARDECL(unsigned char, tmp_data);
637 VARDECL(unsigned char, rp_);
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400638 int nb_frames;
639 int bak_mode, bak_bandwidth, bak_channels;
Jean-Marc Valind970a852011-09-08 21:41:29 -0400640 OpusRepacketizer *rp;
641 int bytes_per_frame;
642
643 nb_frames = frame_size > st->Fs/25 ? 3 : 2;
644 bytes_per_frame = max_data_bytes/nb_frames-3;
645
646 ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char);
647 ALLOC(rp_, opus_repacketizer_get_size(), unsigned char);
648
649 rp = opus_repacketizer_init((OpusRepacketizer*)rp_);
Jean-Marc Valind3358b12011-06-14 14:48:53 -0400650
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400651 bak_mode = st->user_forced_mode;
652 bak_bandwidth = st->user_bandwidth;
653 bak_channels = st->force_channels;
654
655 st->user_forced_mode = st->mode;
656 st->user_bandwidth = st->bandwidth;
657 st->force_channels = st->stream_channels;
658
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400659 for (i=0;i<nb_frames;i++)
660 {
661 int tmp_len;
Jean-Marc Valind970a852011-09-08 21:41:29 -0400662 tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50, tmp_data+i*bytes_per_frame, bytes_per_frame);
663 ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len);
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400664 }
665 ret = opus_repacketizer_out(rp, data, max_data_bytes);
666
Jean-Marc Valine4336a52011-09-08 18:19:50 -0400667 st->user_forced_mode = bak_mode;
668 st->user_bandwidth = bak_bandwidth;
669 st->force_channels = bak_channels;
670 RESTORE_STACK;
671 return ret;
672 }
Jean-Marc Valin81936d52011-08-13 01:44:39 -0400673 /* CELT mode doesn't support mediumband, use wideband instead */
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400674 if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
675 st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
Jean-Marc Valin81936d52011-08-13 01:44:39 -0400676
677 /* Chooses the appropriate mode for speech
Jean-Marc Valin07dceb72011-09-08 13:53:20 -0400678 *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400679 if (st->mode == MODE_SILK_ONLY && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500680 st->mode = MODE_HYBRID;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400681 if (st->mode == MODE_HYBRID && st->bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -0500682 st->mode = MODE_SILK_ONLY;
683
Jean-Marc Valin904e7a82011-09-11 14:29:46 -0400684 /* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */
685 if (max_data_bytes < 8000*frame_size / (st->Fs * 8))
686 st->mode = MODE_CELT_ONLY;
Jean-Marc Valinc681bd02011-09-02 14:47:26 -0400687 /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, st->bandwidth); */
Jean-Marc Valin904e7a82011-09-11 14:29:46 -0400688 bytes_target = IMIN(max_data_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500689
Ralph Giles641eea82011-08-02 10:06:59 -0700690 data += 1;
Jean-Marc Valin606250a2011-02-15 14:31:21 -0500691
Ralph Giles641eea82011-08-02 10:06:59 -0700692 ec_enc_init(&enc, data, max_data_bytes-1);
Jean-Marc Valin24af3032010-06-30 14:29:45 -0400693
Jean-Marc Valind186c912011-09-08 15:13:46 -0400694 ALLOC(pcm_buf, (delay_compensation+frame_size)*st->channels, opus_val16);
695 for (i=0;i<delay_compensation*st->channels;i++)
696 pcm_buf[i] = st->delay_buffer[(st->encoder_buffer-delay_compensation)*st->channels+i];
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400697
698 if (st->mode == MODE_CELT_ONLY)
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700699 hp_freq_smth1 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400700 else
701 hp_freq_smth1 = ((silk_encoder*)silk_enc)->state_Fxx[0].sCmn.variable_HP_smth1_Q15;
702
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700703 st->variable_HP_smth2_Q15 = silk_SMLAWB( st->variable_HP_smth2_Q15,
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400704 hp_freq_smth1 - st->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) );
705
706 /* convert from log scale to Hertz */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700707 cutoff_Hz = silk_log2lin( silk_RSHIFT( st->variable_HP_smth2_Q15, 8 ) );
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400708
709 if (st->application == OPUS_APPLICATION_VOIP)
710 {
Jean-Marc Valind186c912011-09-08 15:13:46 -0400711 hp_cutoff(pcm, cutoff_Hz, &pcm_buf[delay_compensation*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400712 } else {
713 for (i=0;i<frame_size*st->channels;i++)
Jean-Marc Valind186c912011-09-08 15:13:46 -0400714 pcm_buf[delay_compensation*st->channels + i] = pcm[i];
Jean-Marc Valin957f7f12011-09-01 18:02:43 -0400715 }
Jean-Marc Valin2f0ca762011-09-01 16:56:40 -0400716
Ralph Giles641eea82011-08-02 10:06:59 -0700717 /* SILK processing */
Jean-Marc Valin606250a2011-02-15 14:31:21 -0500718 if (st->mode != MODE_CELT_ONLY)
719 {
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400720#ifdef FIXED_POINT
721 const opus_int16 *pcm_silk;
722#else
723 VARDECL(opus_int16, pcm_silk);
724 ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
725#endif
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500726 st->silk_mode.bitRate = st->bitrate_bps - 8*st->Fs/frame_size;
727 if( st->mode == MODE_HYBRID ) {
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400728 st->silk_mode.bitRate /= st->stream_channels;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400729 if( st->bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) {
Karsten Vandborg Sorensen78054752011-02-03 09:36:59 -0500730 if( st->Fs == 100 * frame_size ) {
731 /* 24 kHz, 10 ms */
Koen Vos5ad41a32011-02-04 00:49:48 -0500732 st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 2000 + st->use_vbr * 1000 ) * 2 ) / 3;
Karsten Vandborg Sorensen78054752011-02-03 09:36:59 -0500733 } else {
734 /* 24 kHz, 20 ms */
Koen Vos5ad41a32011-02-04 00:49:48 -0500735 st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 1000 + st->use_vbr * 1000 ) * 2 ) / 3;
Karsten Vandborg Sorensen78054752011-02-03 09:36:59 -0500736 }
737 } else {
738 if( st->Fs == 100 * frame_size ) {
739 /* 48 kHz, 10 ms */
Koen Vos5ad41a32011-02-04 00:49:48 -0500740 st->silk_mode.bitRate = ( st->silk_mode.bitRate + 8000 + st->use_vbr * 3000 ) / 2;
Karsten Vandborg Sorensen78054752011-02-03 09:36:59 -0500741 } else {
742 /* 48 kHz, 20 ms */
Koen Vos5ad41a32011-02-04 00:49:48 -0500743 st->silk_mode.bitRate = ( st->silk_mode.bitRate + 9000 + st->use_vbr * 1000 ) / 2;
Karsten Vandborg Sorensen78054752011-02-03 09:36:59 -0500744 }
745 }
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400746 st->silk_mode.bitRate *= st->stream_channels;
Koen Vos03c1d662011-02-17 16:54:44 -0500747 /* don't let SILK use more than 80% */
748 if( st->silk_mode.bitRate > ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5 ) {
749 st->silk_mode.bitRate = ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5;
750 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500751 }
Jean-Marc Valin904e7a82011-09-11 14:29:46 -0400752 /* SILK is not allow to use more than 50% of max_data_bytes */
753 if (max_data_bytes < 2*st->silk_mode.bitRate*frame_size / (st->Fs * 8))
754 st->silk_mode.bitRate = max_data_bytes*st->Fs*4/frame_size;
Jean-Marc Valin862e1822010-07-20 12:19:00 -0400755
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500756 st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400757 st->silk_mode.nChannelsAPI = st->channels;
758 st->silk_mode.nChannelsInternal = st->stream_channels;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400759 if (st->bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
Ralph Giles641eea82011-08-02 10:06:59 -0700760 st->silk_mode.desiredInternalSampleRate = 8000;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -0400761 } else if (st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
Ralph Giles641eea82011-08-02 10:06:59 -0700762 st->silk_mode.desiredInternalSampleRate = 12000;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500763 } else {
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700764 silk_assert( st->mode == MODE_HYBRID || st->bandwidth == OPUS_BANDWIDTH_WIDEBAND );
Jean-Marc Valind8f90972011-04-27 10:06:53 -0400765 st->silk_mode.desiredInternalSampleRate = 16000;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500766 }
767 if( st->mode == MODE_HYBRID ) {
768 /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
Koen Vos1e1562c2011-02-14 15:04:59 -0500769 st->silk_mode.minInternalSampleRate = 16000;
770 } else {
771 st->silk_mode.minInternalSampleRate = 8000;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500772 }
Jean-Marc Valind8f90972011-04-27 10:06:53 -0400773 st->silk_mode.maxInternalSampleRate = 16000;
Jean-Marc Valinb5be8262010-11-12 06:47:46 +0800774
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500775 /* Call SILK encoder for the low band */
Jean-Marc Valin66c612e2011-08-15 14:08:57 -0400776 nBytes = IMIN(1275, max_data_bytes-1);
Jean-Marc Valine3de5052011-02-20 12:23:48 -0500777 if (prefill)
Jean-Marc Valina93f5012011-03-03 15:50:08 -0500778 {
779 int zero=0;
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400780#ifdef FIXED_POINT
781 pcm_silk = st->delay_buffer;
782#else
783 for (i=0;i<st->encoder_buffer*st->channels;i++)
Ralph Giles04cca282011-08-24 00:29:29 -0400784 pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]);
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400785#endif
786 silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 );
Jean-Marc Valina93f5012011-03-03 15:50:08 -0500787 }
Jean-Marc Valine3de5052011-02-20 12:23:48 -0500788
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400789#ifdef FIXED_POINT
Jean-Marc Valind186c912011-09-08 15:13:46 -0400790 pcm_silk = pcm_buf+delay_compensation*st->channels;
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400791#else
792 for (i=0;i<frame_size*st->channels;i++)
Jean-Marc Valind186c912011-09-08 15:13:46 -0400793 pcm_silk[i] = FLOAT2INT16(pcm_buf[delay_compensation*st->channels + i]);
Jean-Marc Valin222494f2011-08-17 15:53:37 -0400794#endif
795 ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 );
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500796 if( ret ) {
Jean-Marc Valinbe89c392011-08-30 12:39:51 -0400797 /*fprintf (stderr, "SILK encode error: %d\n", ret);*/
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500798 /* Handle error */
Jean-Marc Valinbe89c392011-08-30 12:39:51 -0400799 return OPUS_INTERNAL_ERROR;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500800 }
Jean-Marc Valin617fcd22011-03-16 22:11:53 -0400801 if (nBytes==0)
Jean-Marc Valin421a6282011-08-18 14:32:16 -0400802 {
Jean-Marc Valin69bfc672011-08-29 21:46:17 -0400803 data[-1] = gen_toc(st->mode, st->Fs/frame_size, st->bandwidth, silk_internal_bandwidth, st->stream_channels);
Jean-Marc Valin44e27dd2011-08-29 23:35:17 -0400804 RESTORE_STACK;
Jean-Marc Valin421a6282011-08-18 14:32:16 -0400805 return 1;
806 }
Jean-Marc Valin69bfc672011-08-29 21:46:17 -0400807 /* Extract SILK internal bandwidth for signaling in first byte */
808 if( st->mode == MODE_SILK_ONLY ) {
809 if( st->silk_mode.internalSampleRate == 8000 ) {
810 silk_internal_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
811 } else if( st->silk_mode.internalSampleRate == 12000 ) {
812 silk_internal_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
813 } else if( st->silk_mode.internalSampleRate == 16000 ) {
814 silk_internal_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
815 }
816 } else {
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700817 silk_assert( st->silk_mode.internalSampleRate == 16000 );
Jean-Marc Valin69bfc672011-08-29 21:46:17 -0400818 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500819 }
Jean-Marc Valin67008d22010-07-20 11:13:30 -0400820
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500821 /* CELT processing */
Ralph Giles641eea82011-08-02 10:06:59 -0700822 {
823 int endband=21;
Jean-Marc Valine2d1ef12010-07-06 15:39:19 -0400824
Ralph Giles641eea82011-08-02 10:06:59 -0700825 switch(st->bandwidth)
826 {
827 case OPUS_BANDWIDTH_NARROWBAND:
828 endband = 13;
829 break;
830 case OPUS_BANDWIDTH_MEDIUMBAND:
Ralph Giles04cca282011-08-24 00:29:29 -0400831 case OPUS_BANDWIDTH_WIDEBAND:
832 endband = 17;
833 break;
Ralph Giles641eea82011-08-02 10:06:59 -0700834 case OPUS_BANDWIDTH_SUPERWIDEBAND:
835 endband = 19;
836 break;
837 case OPUS_BANDWIDTH_FULLBAND:
838 endband = 21;
839 break;
840 }
841 celt_encoder_ctl(celt_enc, CELT_SET_END_BAND(endband));
842 celt_encoder_ctl(celt_enc, CELT_SET_CHANNELS(st->stream_channels));
843 }
844 if (st->mode != MODE_SILK_ONLY)
845 {
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400846 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
Jean-Marc Valin663a7fe2011-09-06 14:05:19 -0400847 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
Jean-Marc Valin606250a2011-02-15 14:31:21 -0500848 if (st->prev_mode == MODE_SILK_ONLY)
849 {
Ralph Giles641eea82011-08-02 10:06:59 -0700850 unsigned char dummy[10];
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400851 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
Ralph Giles641eea82011-08-02 10:06:59 -0700852 celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
853 celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
Jean-Marc Valin92675062011-09-11 22:00:46 -0400854 /* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */
Jean-Marc Valind186c912011-09-08 15:13:46 -0400855 celt_encode_with_ec(celt_enc, &st->delay_buffer[(st->encoder_buffer-delay_compensation-st->Fs/400)*st->channels], st->Fs/400, dummy, 10, NULL);
Jean-Marc Valin606250a2011-02-15 14:31:21 -0500856 } else {
Ralph Giles641eea82011-08-02 10:06:59 -0700857 celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(2));
Jean-Marc Valin606250a2011-02-15 14:31:21 -0500858 }
Jean-Marc Valine2a09db2011-03-02 17:54:43 -0500859
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500860 if (st->mode == MODE_HYBRID)
861 {
862 int len;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500863
Timothy B. Terriberrya1dd0fc2011-02-03 14:52:50 -0800864 len = (ec_tell(&enc)+7)>>3;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500865 if( st->use_vbr ) {
Koen Vos5ad41a32011-02-04 00:49:48 -0500866 nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500867 } else {
868 /* check if SILK used up too much */
869 nb_compr_bytes = len > bytes_target ? len : bytes_target;
870 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500871 } else {
Jean-Marc Valind9ad6e12011-02-01 18:08:41 -0500872 if (st->use_vbr)
873 {
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400874 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1));
875 celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint));
876 celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps));
Jean-Marc Valind9ad6e12011-02-01 18:08:41 -0500877 nb_compr_bytes = max_data_bytes-1;
878 } else {
879 nb_compr_bytes = bytes_target;
880 }
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -0500881 }
882
Ralph Giles641eea82011-08-02 10:06:59 -0700883 } else {
884 nb_compr_bytes = 0;
885 }
Jean-Marc Valinc8a20b72010-07-21 14:07:11 -0400886
Jean-Marc Valind186c912011-09-08 15:13:46 -0400887 for (i=0;i<st->channels*(st->encoder_buffer-(frame_size+delay_compensation));i++)
Jean-Marc Valin12c39922011-09-04 11:00:29 -0400888 st->delay_buffer[i] = st->delay_buffer[i+st->channels*frame_size];
889 for (;i<st->encoder_buffer*st->channels;i++)
Jean-Marc Valind186c912011-09-08 15:13:46 -0400890 st->delay_buffer[i] = pcm_buf[(frame_size+delay_compensation-st->encoder_buffer)*st->channels+i];
Jean-Marc Valin2f0ca762011-09-01 16:56:40 -0400891
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400892
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400893 if (st->mode != MODE_HYBRID || st->stream_channels==1)
Jean-Marc Valinbc2eebd2011-10-04 11:59:32 -0400894 st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14 = 1<<14;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400895 if( st->channels == 2 ) {
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400896 /* Apply stereo width reduction (at low bitrates) */
897 if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) {
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -0400898 opus_val16 g1, g2;
899 const CELTMode *celt_mode;
900
901 celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode));
902 g1 = st->hybrid_stereo_width_Q14;
903 g2 = st->silk_mode.stereoWidth_Q14;
904#ifdef FIXED_POINT
905 g1 *= (1./16384);
906 g2 *= (1./16384);
907#else
908 g1 = g1==16384 ? Q15ONE : SHL16(g1,1);
909 g2 = g2==16384 ? Q15ONE : SHL16(g2,1);
910#endif
911 stereo_fade(pcm_buf, pcm_buf, g1, g2, celt_mode->overlap,
912 frame_size, st->channels, celt_mode->window, st->Fs);
Jean-Marc Valin103302b2011-05-19 17:17:44 -0400913 st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14;
914 }
915 }
916
Jean-Marc Valine5736ae2011-09-05 10:28:27 -0400917 if (st->mode != MODE_CELT_ONLY && ec_tell(&enc)+29+8*(st->mode == MODE_HYBRID) < 8*nb_compr_bytes)
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500918 {
919 /* Check if we have a redundant 0-8 kHz band */
920 ec_enc_bit_logp(&enc, redundancy, 12);
921 if (redundancy)
922 {
Jean-Marc Valine5736ae2011-09-05 10:28:27 -0400923 int max_redundancy;
924 ec_enc_bit_logp(&enc, celt_to_silk, 1);
925 max_redundancy = nb_compr_bytes-((ec_tell(&enc)+7)>>3)-(st->mode == MODE_HYBRID);
Jean-Marc Valin51ac8e62011-08-15 22:06:02 -0400926 /* Target the same bit-rate for redundancy as for the rest,
927 up to a max of 257 bytes */
Jean-Marc Valine5736ae2011-09-05 10:28:27 -0400928 redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600);
929 redundancy_bytes = IMIN(257, IMAX(2, redundancy_bytes));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500930 if (st->mode == MODE_HYBRID)
Ralph Giles04cca282011-08-24 00:29:29 -0400931 ec_enc_uint(&enc, redundancy_bytes-2, 256);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500932 }
Jean-Marc Valine5736ae2011-09-05 10:28:27 -0400933 } else {
934 redundancy = 0;
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500935 }
936
Gregory Maxwell7d1df732011-09-05 11:28:28 -0400937 if (st->mode != MODE_CELT_ONLY)start_band=17;
938
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500939 if (st->mode == MODE_SILK_ONLY)
940 {
941 ret = (ec_tell(&enc)+7)>>3;
942 ec_enc_done(&enc);
Gregory Maxwell03f7de72011-08-15 17:25:59 -0400943 /*When in LPC only mode it's perfectly
944 reasonable to strip off trailing zero bytes as
945 the required range decoder behavior is to
946 fill these in. This can't be done when the MDCT
947 modes are used because the decoder needs to know
948 the actual length for allocation purposes.*/
949 if(!redundancy)
950 while(ret>2&&data[ret-1]==0)ret--;
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500951 nb_compr_bytes = ret;
Jean-Marc Valin51ac8e62011-08-15 22:06:02 -0400952 } else {
953 nb_compr_bytes = IMIN(1275-redundancy_bytes, nb_compr_bytes);
954 ec_enc_shrink(&enc, nb_compr_bytes);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500955 }
956
Jean-Marc Valin51ac8e62011-08-15 22:06:02 -0400957
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500958 /* 5 ms redundant frame for CELT->SILK */
959 if (redundancy && celt_to_silk)
960 {
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400961 celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400962 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
Jean-Marc Valin58686e62011-08-31 15:08:12 -0400963 celt_encode_with_ec(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes, NULL);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400964 celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng));
965 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500966 }
967
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400968 celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(start_band));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500969
970 if (st->mode != MODE_SILK_ONLY)
Ralph Giles641eea82011-08-02 10:06:59 -0700971 {
972 ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
Jean-Marc Valin69f44c52011-09-07 02:43:23 -0400973 if (ret < 0)
974 return OPUS_INTERNAL_ERROR;
Ralph Giles641eea82011-08-02 10:06:59 -0700975 }
Jean-Marc Valin24f36e02010-07-06 14:41:20 -0400976
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500977 /* 5 ms redundant frame for SILK->CELT */
978 if (redundancy && !celt_to_silk)
979 {
980 int N2, N4;
981 N2 = st->Fs/200;
982 N4 = st->Fs/400;
983
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400984 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
Jean-Marc Valin5095c472011-05-05 19:47:48 -0400985 celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
986 celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500987
Jean-Marc Valin92675062011-09-11 22:00:46 -0400988 /* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */
Jean-Marc Valin58686e62011-08-31 15:08:12 -0400989 celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, data+nb_compr_bytes, redundancy_bytes, NULL);
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500990
Jean-Marc Valin58686e62011-08-31 15:08:12 -0400991 celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes, NULL);
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -0400992 celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng));
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500993 }
994
995
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -0500996
Ralph Giles641eea82011-08-02 10:06:59 -0700997 /* Signalling the mode in the first byte */
998 data--;
Jean-Marc Valin69bfc672011-08-29 21:46:17 -0400999 data[0] = gen_toc(st->mode, st->Fs/frame_size, st->bandwidth, silk_internal_bandwidth, st->stream_channels);
Jean-Marc Valin57de8a32010-09-07 17:37:56 -04001000
Jean-Marc Valin06cee2b2011-08-19 16:11:41 -04001001 st->rangeFinal = enc.rng ^ redundant_rng;
Ralph Giles3f0962c2011-07-29 14:01:54 -07001002
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001003 if (to_celt)
1004 st->prev_mode = MODE_CELT_ONLY;
1005 else
1006 st->prev_mode = st->mode;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001007 st->prev_channels = st->stream_channels;
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001008 st->prev_framesize = frame_size;
Jean-Marc Valinde3e16c2011-10-03 00:39:29 -04001009
Jean-Marc Valinc1673fa2011-04-28 08:04:20 -04001010 st->first = 0;
Jean-Marc Valin44e27dd2011-08-29 23:35:17 -04001011 RESTORE_STACK;
Jean-Marc Valin0c0c5f92011-03-07 20:54:33 -05001012 return ret+1+redundancy_bytes;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001013}
1014
Jean-Marc Valin222494f2011-08-17 15:53:37 -04001015#ifdef FIXED_POINT
1016
1017#ifndef DISABLE_FLOAT_API
1018int opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size,
1019 unsigned char *data, int max_data_bytes)
1020{
1021 int i, ret;
1022 VARDECL(opus_int16, in);
1023 ALLOC_STACK;
1024
1025 ALLOC(in, frame_size*st->channels, opus_int16);
1026
1027 for (i=0;i<frame_size*st->channels;i++)
1028 in[i] = FLOAT2INT16(pcm[i]);
1029 ret = opus_encode(st, in, frame_size, data, max_data_bytes);
1030 RESTORE_STACK;
1031 return ret;
1032}
1033#endif
1034
1035#else
1036int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size,
1037 unsigned char *data, int max_data_bytes)
1038{
1039 int i, ret;
1040 VARDECL(float, in);
1041 ALLOC_STACK;
1042
1043 ALLOC(in, frame_size*st->channels, float);
1044
1045 for (i=0;i<frame_size*st->channels;i++)
1046 in[i] = (1./32768)*pcm[i];
1047 ret = opus_encode_float(st, in, frame_size, data, max_data_bytes);
1048 RESTORE_STACK;
1049 return ret;
1050}
1051#endif
1052
1053
Jean-Marc Valin955f94c2011-03-08 22:12:43 -05001054int opus_encoder_ctl(OpusEncoder *st, int request, ...)
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001055{
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001056 int ret;
Ralph Giles641eea82011-08-02 10:06:59 -07001057 CELTEncoder *celt_enc;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001058 va_list ap;
1059
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001060 ret = OPUS_OK;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001061 va_start(ap, request);
1062
Jean-Marc Valin5095c472011-05-05 19:47:48 -04001063 celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
1064
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001065 switch (request)
1066 {
Jean-Marc Valin69549ac2011-08-18 17:28:28 -04001067 case OPUS_SET_APPLICATION_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001068 {
Ralph Giles04cca282011-08-24 00:29:29 -04001069 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -04001070 if ( (value != OPUS_APPLICATION_VOIP && value != OPUS_APPLICATION_AUDIO
1071 && value != OPUS_APPLICATION_RESTRICTED_LOWDELAY)
1072 || (!st->first && st->application != value))
1073 {
1074 ret = OPUS_BAD_ARG;
1075 break;
1076 }
Jean-Marc Valin69549ac2011-08-18 17:28:28 -04001077 st->application = value;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001078 }
1079 break;
Jean-Marc Valin69549ac2011-08-18 17:28:28 -04001080 case OPUS_GET_APPLICATION_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001081 {
Ralph Giles04cca282011-08-24 00:29:29 -04001082 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001083 *value = st->application;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001084 }
1085 break;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001086 case OPUS_SET_BITRATE_REQUEST:
1087 {
Ralph Giles04cca282011-08-24 00:29:29 -04001088 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001089 if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
Jean-Marc Valinba547462011-05-10 17:54:41 -04001090 {
1091 if (value <= 0)
1092 goto bad_arg;
1093 else if (value <= 500)
1094 value = 500;
Jean-Marc Valin69f44c52011-09-07 02:43:23 -04001095 else if (value > (opus_int32)300000*st->channels)
1096 value = (opus_int32)300000*st->channels;
Jean-Marc Valinba547462011-05-10 17:54:41 -04001097 }
1098 st->user_bitrate_bps = value;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001099 }
1100 break;
1101 case OPUS_GET_BITRATE_REQUEST:
1102 {
Ralph Giles04cca282011-08-24 00:29:29 -04001103 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001104 *value = user_bitrate_to_bitrate(st, st->prev_framesize, 1276);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001105 }
1106 break;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001107 case OPUS_SET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001108 {
Ralph Giles04cca282011-08-24 00:29:29 -04001109 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwellb9f443d2011-10-04 01:20:39 -04001110 if((value<1 || value>st->channels) && value != OPUS_AUTO)
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001111 return OPUS_BAD_ARG;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001112 st->force_channels = value;
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001113 }
1114 break;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001115 case OPUS_GET_FORCE_CHANNELS_REQUEST:
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001116 {
Ralph Giles04cca282011-08-24 00:29:29 -04001117 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001118 *value = st->force_channels;
Jean-Marc Valin103302b2011-05-19 17:17:44 -04001119 }
1120 break;
Jean-Marc Valin05dd36a2010-10-18 12:50:49 -04001121 case OPUS_SET_BANDWIDTH_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001122 {
Ralph Giles04cca282011-08-24 00:29:29 -04001123 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001124 if ((value < OPUS_BANDWIDTH_NARROWBAND || value > OPUS_BANDWIDTH_FULLBAND) && value != OPUS_AUTO)
Ralph Giles04cca282011-08-24 00:29:29 -04001125 return OPUS_BAD_ARG;
Jean-Marc Valin955f94c2011-03-08 22:12:43 -05001126 st->user_bandwidth = value;
Jean-Marc Valin541df0a2011-05-26 00:22:58 -04001127 if (st->user_bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001128 st->silk_mode.maxInternalSampleRate = 8000;
Gregory Maxwell87141892011-10-02 03:19:15 -04001129 } else if (st->user_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001130 st->silk_mode.maxInternalSampleRate = 12000;
1131 } else {
1132 st->silk_mode.maxInternalSampleRate = 16000;
1133 }
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001134 }
1135 break;
Jean-Marc Valin05dd36a2010-10-18 12:50:49 -04001136 case OPUS_GET_BANDWIDTH_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001137 {
Ralph Giles04cca282011-08-24 00:29:29 -04001138 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001139 *value = st->bandwidth;
1140 }
1141 break;
Jean-Marc Valind4827732011-08-19 17:07:16 -04001142 case OPUS_SET_DTX_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001143 {
Ralph Giles04cca282011-08-24 00:29:29 -04001144 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001145 if(value<0 || value>1)
1146 return OPUS_BAD_ARG;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001147 st->silk_mode.useDTX = value;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001148 }
1149 break;
Jean-Marc Valind4827732011-08-19 17:07:16 -04001150 case OPUS_GET_DTX_REQUEST:
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001151 {
Ralph Giles04cca282011-08-24 00:29:29 -04001152 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001153 *value = st->silk_mode.useDTX;
1154 }
1155 break;
1156 case OPUS_SET_COMPLEXITY_REQUEST:
1157 {
Ralph Giles04cca282011-08-24 00:29:29 -04001158 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001159 if(value<0 || value>10)
1160 return OPUS_BAD_ARG;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001161 st->silk_mode.complexity = value;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001162 celt_encoder_ctl(celt_enc, OPUS_SET_COMPLEXITY(value));
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001163 }
1164 break;
1165 case OPUS_GET_COMPLEXITY_REQUEST:
1166 {
Ralph Giles04cca282011-08-24 00:29:29 -04001167 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001168 *value = st->silk_mode.complexity;
1169 }
1170 break;
Jean-Marc Valine766d9f2011-08-28 20:27:18 -04001171 case OPUS_SET_INBAND_FEC_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001172 {
Ralph Giles04cca282011-08-24 00:29:29 -04001173 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001174 if(value<0 || value>1)
1175 return OPUS_BAD_ARG;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001176 st->silk_mode.useInBandFEC = value;
1177 }
1178 break;
Jean-Marc Valine766d9f2011-08-28 20:27:18 -04001179 case OPUS_GET_INBAND_FEC_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001180 {
Ralph Giles04cca282011-08-24 00:29:29 -04001181 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001182 *value = st->silk_mode.useInBandFEC;
1183 }
1184 break;
1185 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
1186 {
Ralph Giles04cca282011-08-24 00:29:29 -04001187 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valind2124cd2011-04-25 13:36:14 -04001188 if (value < 0 || value > 100)
1189 return OPUS_BAD_ARG;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001190 st->silk_mode.packetLossPercentage = value;
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001191 celt_encoder_ctl(celt_enc, OPUS_SET_PACKET_LOSS_PERC(value));
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001192 }
1193 break;
1194 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
1195 {
Ralph Giles04cca282011-08-24 00:29:29 -04001196 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001197 *value = st->silk_mode.packetLossPercentage;
1198 }
1199 break;
Jean-Marc Valind7f67002011-08-18 16:55:24 -04001200 case OPUS_SET_VBR_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001201 {
Ralph Giles04cca282011-08-24 00:29:29 -04001202 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001203 if(value<0 || value>1)
1204 return OPUS_BAD_ARG;
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001205 st->use_vbr = value;
1206 st->silk_mode.useCBR = 1-value;
1207 }
1208 break;
Jean-Marc Valind7f67002011-08-18 16:55:24 -04001209 case OPUS_GET_VBR_REQUEST:
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001210 {
Ralph Giles04cca282011-08-24 00:29:29 -04001211 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin2b68ea92011-02-01 10:35:23 -05001212 *value = st->use_vbr;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001213 }
1214 break;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001215 case OPUS_SET_VOICE_RATIO_REQUEST:
1216 {
Ralph Giles04cca282011-08-24 00:29:29 -04001217 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valinc681bd02011-09-02 14:47:26 -04001218 if (value>100 || value<-1)
Jean-Marc Valind2124cd2011-04-25 13:36:14 -04001219 goto bad_arg;
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001220 st->voice_ratio = value;
1221 }
1222 break;
1223 case OPUS_GET_VOICE_RATIO_REQUEST:
1224 {
Ralph Giles04cca282011-08-24 00:29:29 -04001225 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valinf9bc4602011-03-08 14:57:46 -05001226 *value = st->voice_ratio;
1227 }
1228 break;
Jean-Marc Valinb55b6612011-03-14 15:11:44 -04001229 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
1230 {
Ralph Giles04cca282011-08-24 00:29:29 -04001231 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001232 if(value<0 || value>1)
1233 return OPUS_BAD_ARG;
Jean-Marc Valinb55b6612011-03-14 15:11:44 -04001234 st->vbr_constraint = value;
1235 }
1236 break;
1237 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
1238 {
Ralph Giles04cca282011-08-24 00:29:29 -04001239 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valinb55b6612011-03-14 15:11:44 -04001240 *value = st->vbr_constraint;
1241 }
1242 break;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04001243 case OPUS_SET_SIGNAL_REQUEST:
1244 {
Ralph Giles04cca282011-08-24 00:29:29 -04001245 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwell220a7d42011-10-01 20:30:16 -04001246 if(value!=OPUS_AUTO && value!=OPUS_SIGNAL_VOICE && value!=OPUS_SIGNAL_MUSIC)
1247 return OPUS_BAD_ARG;
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04001248 st->signal_type = value;
1249 }
1250 break;
1251 case OPUS_GET_SIGNAL_REQUEST:
1252 {
Ralph Giles04cca282011-08-24 00:29:29 -04001253 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valin00cb6f72011-05-26 15:06:30 -04001254 *value = st->signal_type;
1255 }
1256 break;
Jean-Marc Valin9d8b5192011-08-03 12:44:37 -04001257 case OPUS_GET_LOOKAHEAD_REQUEST:
1258 {
Ralph Giles04cca282011-08-24 00:29:29 -04001259 opus_int32 *value = va_arg(ap, opus_int32*);
Jean-Marc Valind186c912011-09-08 15:13:46 -04001260 *value = st->Fs/400;
Jean-Marc Valin68bc8c02011-09-09 11:10:48 -04001261 if (st->application != OPUS_APPLICATION_RESTRICTED_LOWDELAY)
Jean-Marc Valind186c912011-09-08 15:13:46 -04001262 *value += st->delay_compensation;
Jean-Marc Valin9d8b5192011-08-03 12:44:37 -04001263 }
1264 break;
Jean-Marc Valind4827732011-08-19 17:07:16 -04001265 case OPUS_GET_FINAL_RANGE_REQUEST:
1266 {
1267 opus_uint32 *value = va_arg(ap, opus_uint32*);
1268 *value = st->rangeFinal;
1269 }
1270 break;
Jean-Marc Valin927488b2011-08-30 20:09:22 -04001271 case OPUS_RESET_STATE:
1272 {
1273 void *silk_enc;
1274 silk_EncControlStruct dummy;
1275 silk_enc = (char*)st+st->silk_enc_offset;
1276
1277 OPUS_CLEAR((char*)&st->OPUS_ENCODER_RESET_START,
Gregory Maxwelld32f9482011-09-04 07:48:20 -04001278 sizeof(OpusEncoder)-
Jean-Marc Valin927488b2011-08-30 20:09:22 -04001279 ((char*)&st->OPUS_ENCODER_RESET_START - (char*)st));
1280
Jean-Marc Valinf9e701a2011-08-31 17:47:48 -04001281 celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
Jean-Marc Valin927488b2011-08-30 20:09:22 -04001282 silk_InitEncoder( silk_enc, &dummy );
1283 st->stream_channels = st->channels;
1284 st->hybrid_stereo_width_Q14 = 1 << 14;
1285 st->first = 1;
1286 st->mode = MODE_HYBRID;
1287 st->bandwidth = OPUS_BANDWIDTH_FULLBAND;
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -07001288 st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
Jean-Marc Valin927488b2011-08-30 20:09:22 -04001289 }
1290 break;
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001291 case OPUS_SET_FORCE_MODE_REQUEST:
1292 {
1293 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwelled921b02011-10-02 20:04:28 -04001294 if ((value < MODE_SILK_ONLY || value > MODE_CELT_ONLY) && value != OPUS_AUTO)
Jean-Marc Valin07dceb72011-09-08 13:53:20 -04001295 goto bad_arg;
1296 st->user_forced_mode = value;
1297 }
1298 break;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001299 default:
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001300 /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/
Jean-Marc Valin06237d72011-09-01 13:20:40 -04001301 ret = OPUS_UNIMPLEMENTED;
Jean-Marc Valin24f36e02010-07-06 14:41:20 -04001302 break;
Jean-Marc Valinc5ea0742010-07-05 11:11:54 -04001303 }
Alfred E. Heggestad3d31d702010-07-27 16:38:04 +02001304 va_end(ap);
Jean-Marc Valinbe89c392011-08-30 12:39:51 -04001305 return ret;
Jean-Marc Valind2124cd2011-04-25 13:36:14 -04001306bad_arg:
1307 va_end(ap);
1308 return OPUS_BAD_ARG;
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04001309}
1310
Jean-Marc Valin05dd36a2010-10-18 12:50:49 -04001311void opus_encoder_destroy(OpusEncoder *st)
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04001312{
Jean-Marc Valin07f88402011-08-29 15:08:51 -04001313 opus_free(st);
Jean-Marc Valin3e66e912010-06-30 14:16:14 -04001314}