opus_encoder.c 21.1 KB
Newer Older
1
2
/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
   Written by Jean-Marc Valin and Koen Vos */
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

   - Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>
33
#include <stdio.h>
34
#include <stdarg.h>
35
#include "celt.h"
Jean-Marc Valin's avatar
Jean-Marc Valin committed
36
#include "opus_encoder.h"
Jean-Marc Valin's avatar
Jean-Marc Valin committed
37
38
#include "entenc.h"
#include "modes.h"
39
#include "SKP_Silk_SDK_API.h"
40

41
OpusEncoder *opus_encoder_create(int Fs, int channels)
42
{
Jean-Marc Valin's avatar
Jean-Marc Valin committed
43
    int err;
44
    char *raw_state;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
45
	OpusEncoder *st;
46
	int ret, silkEncSizeBytes, celtEncSizeBytes;
47

48
    /* Create SILK encoder */
49
    ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes );
50
51
52
    if( ret ) {
    	/* Handle error */
    }
Jean-Marc Valin's avatar
Jean-Marc Valin committed
53
    celtEncSizeBytes = celt_encoder_get_size(channels);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
54
55
56
57
    raw_state = calloc(sizeof(OpusEncoder)+silkEncSizeBytes+celtEncSizeBytes, 1);
    st = (OpusEncoder*)raw_state;
    st->silk_enc = (void*)(raw_state+sizeof(OpusEncoder));
    st->celt_enc = (CELTEncoder*)(raw_state+sizeof(OpusEncoder)+silkEncSizeBytes);
58
    st->stream_channels = st->channels = channels;
59
60

    st->Fs = Fs;
61

62
    ret = SKP_Silk_SDK_InitEncoder( st->silk_enc, &st->silk_mode );
63
64
65
    if( ret ) {
        /* Handle error */
    }
66

67
68
69
70
71
72
73
74
    /* default SILK parameters */
    st->silk_mode.API_sampleRate        = st->Fs;
    st->silk_mode.maxInternalSampleRate = 16000;
    st->silk_mode.minInternalSampleRate = 8000;
    st->silk_mode.payloadSize_ms        = 20;
    st->silk_mode.packetLossPercentage  = 0;
    st->silk_mode.useInBandFEC          = 0;
    st->silk_mode.useDTX                = 0;
Koen Vos's avatar
Koen Vos committed
75
    st->silk_mode.complexity            = 10;
76

77
    /* Create CELT encoder */
78
	/* Initialize CELT encoder */
Jean-Marc Valin's avatar
Jean-Marc Valin committed
79
	st->celt_enc = celt_encoder_init(st->celt_enc, Fs, channels, &err);
80
    celt_encoder_ctl(st->celt_enc, CELT_SET_SIGNALLING(0));
81

82
83
	st->mode = MODE_HYBRID;
	st->bandwidth = BANDWIDTH_FULLBAND;
84
85
	st->use_vbr = 0;
	st->bitrate_bps = 32000;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
86
	st->user_mode = OPUS_MODE_AUTO;
87
	st->user_bandwidth = BANDWIDTH_AUTO;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
88
	st->voice_ratio = 90;
89

90
91
92
93
	st->encoder_buffer = st->Fs/100;
	st->delay_compensation = st->Fs/400;
	if (st->Fs > 16000)
		st->delay_compensation += 10;
94
95
96
	return st;
}

Jean-Marc Valin's avatar
Jean-Marc Valin committed
97
int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
98
		unsigned char *data, int max_data_bytes)
99
{
100
    int i;
101
	int ret=0;
102
	SKP_int32 nBytes;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
103
	ec_enc enc;
104
	int framerate, period;
105
106
    int silk_internal_bandwidth;
    int bytes_target;
107
    int prefill=0;
108
    int start_band = 0;
109
    int redundancy = 0;
110
111
112
113
114
    int redundancy_bytes = 0;
    int celt_to_silk = 0;
    short pcm_buf[960*2];
    int nb_compr_bytes;
    int to_celt = 0;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    celt_int32 mono_rate;

    if (st->channels == 2)
    {
        celt_int32 decision_rate;
        decision_rate = st->bitrate_bps + st->voice_ratio*st->voice_ratio;
        if (st->stream_channels == 2)
            decision_rate += 4000;
        else
            decision_rate -= 4000;
        if (decision_rate>48000)
            st->stream_channels = 2;
        else
            st->stream_channels = 1;
    } else {
        st->stream_channels = 1;
    }
    /* Equivalent bit-rate for mono */
    mono_rate = st->bitrate_bps;
    if (st->stream_channels==2)
        mono_rate = (mono_rate+10000)/2;

    /* Mode selection */
    if (st->user_mode==OPUS_MODE_AUTO)
    {
        celt_int32 decision_rate;
        decision_rate = mono_rate - 3*st->voice_ratio*st->voice_ratio;
        if (st->prev_mode == MODE_CELT_ONLY)
            decision_rate += 4000;
        else if (st->prev_mode>0)
            decision_rate -= 4000;
        if (decision_rate>24000)
            st->mode = MODE_CELT_ONLY;
        else
            st->mode = MODE_SILK_ONLY;
    } else if (st->user_mode==OPUS_MODE_VOICE)
    {
        st->mode = MODE_SILK_ONLY;
    } else {/* OPUS_AUDIO_MODE */
        st->mode = MODE_CELT_ONLY;
    }

    /* FIXME: Remove this once SILK supports stereo */
    if (st->channels == 2)
        st->mode = MODE_CELT_ONLY;

    /* Bandwidth selection */
    if (st->mode == MODE_CELT_ONLY)
    {
        if (mono_rate>35000 || (mono_rate>28000 && st->bandwidth==BANDWIDTH_FULLBAND))
            st->bandwidth = BANDWIDTH_FULLBAND;
        else if (mono_rate>28000 || (mono_rate>24000 && st->bandwidth==BANDWIDTH_SUPERWIDEBAND))
            st->bandwidth = BANDWIDTH_SUPERWIDEBAND;
        else if (mono_rate>24000 || (mono_rate>18000 && st->bandwidth==BANDWIDTH_WIDEBAND))
            st->bandwidth = BANDWIDTH_WIDEBAND;
        else
            st->bandwidth = BANDWIDTH_NARROWBAND;
    } else {
        if (mono_rate>28000 || (mono_rate>24000 && st->bandwidth==BANDWIDTH_FULLBAND))
            st->bandwidth = BANDWIDTH_FULLBAND;
        else if (mono_rate>24000 || (mono_rate>18000 && st->bandwidth==BANDWIDTH_SUPERWIDEBAND))
            st->bandwidth = BANDWIDTH_SUPERWIDEBAND;
        else if (mono_rate>18000 || (mono_rate>14000 && st->bandwidth==BANDWIDTH_WIDEBAND))
            st->bandwidth = BANDWIDTH_WIDEBAND;
        else if (mono_rate>14000 || (mono_rate>11000 && st->bandwidth==BANDWIDTH_MEDIUMBAND))
            st->bandwidth = BANDWIDTH_MEDIUMBAND;
        else
            st->bandwidth = BANDWIDTH_NARROWBAND;
    }
184
185
186
187
188
189
190
191
192
193
194
195
196

    if (st->Fs <= 24000 && st->bandwidth > BANDWIDTH_SUPERWIDEBAND)
    	st->bandwidth = BANDWIDTH_SUPERWIDEBAND;
    if (st->Fs <= 16000 && st->bandwidth > BANDWIDTH_WIDEBAND)
    	st->bandwidth = BANDWIDTH_WIDEBAND;
    if (st->Fs <= 12000 && st->bandwidth > BANDWIDTH_MEDIUMBAND)
    	st->bandwidth = BANDWIDTH_MEDIUMBAND;
    if (st->Fs <= 8000 && st->bandwidth > BANDWIDTH_NARROWBAND)
    	st->bandwidth = BANDWIDTH_NARROWBAND;

    if (st->user_bandwidth != BANDWIDTH_AUTO)
    	st->bandwidth = st->user_bandwidth;

Jean-Marc Valin's avatar
Jean-Marc Valin committed
197
198
199
200
201
202
203
204
205
206
207
208
    /* Preventing non-sensical configurations */
    if (frame_size < st->Fs/100 && st->mode != MODE_CELT_ONLY)
        st->mode = MODE_CELT_ONLY;
    if (frame_size > st->Fs/50 && st->mode != MODE_SILK_ONLY)
        st->mode = MODE_SILK_ONLY;
    if (st->mode == MODE_CELT_ONLY && st->bandwidth == BANDWIDTH_MEDIUMBAND)
        st->bandwidth = BANDWIDTH_WIDEBAND;
    if (st->mode == MODE_SILK_ONLY && st->bandwidth > BANDWIDTH_WIDEBAND)
        st->mode = MODE_HYBRID;
    if (st->mode == MODE_HYBRID && st->bandwidth <= BANDWIDTH_WIDEBAND)
        st->mode = MODE_SILK_ONLY;

209
	bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
210

211
	data += 1;
212
213
214
215
	if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
	{
		SKP_SILK_SDK_EncControlStruct dummy;
		SKP_Silk_SDK_InitEncoder( st->silk_enc, &dummy);
216
		prefill=1;
217
	}
218
219
220
221
222
223
224
225
	if (st->prev_mode >0 &&
	        ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
	        || (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)))
	{
	    redundancy = 1;
	    celt_to_silk = (st->mode != MODE_CELT_ONLY);
	    if (!celt_to_silk)
	    {
226
227
228
229
230
231
232
233
	        /* Switch to SILK/hybrid if frame size is 10 ms or more*/
	        if (frame_size >= st->Fs/100)
	        {
		        st->mode = st->prev_mode;
		        to_celt = 1;
	        } else {
	        	redundancy=0;
	        }
234
235
	    }
	}
236

237
	ec_enc_init(&enc, data, max_data_bytes-1);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
238

239
	/* SILK processing */
240
241
    if (st->mode != MODE_CELT_ONLY)
    {
242
243
        st->silk_mode.bitRate = st->bitrate_bps - 8*st->Fs/frame_size;
        if( st->mode == MODE_HYBRID ) {
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
244
245
246
            if( st->bandwidth == BANDWIDTH_SUPERWIDEBAND ) {
                if( st->Fs == 100 * frame_size ) {
                    /* 24 kHz, 10 ms */
Koen Vos's avatar
Koen Vos committed
247
                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 2000 + st->use_vbr * 1000 ) * 2 ) / 3;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
248
249
                } else {
                    /* 24 kHz, 20 ms */
Koen Vos's avatar
Koen Vos committed
250
                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 1000 + st->use_vbr * 1000 ) * 2 ) / 3;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
251
252
253
254
                }
            } else {
                if( st->Fs == 100 * frame_size ) {
                    /* 48 kHz, 10 ms */
Koen Vos's avatar
Koen Vos committed
255
                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 8000 + st->use_vbr * 3000 ) / 2;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
256
257
                } else {
                    /* 48 kHz, 20 ms */
Koen Vos's avatar
Koen Vos committed
258
                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 9000 + st->use_vbr * 1000 ) / 2;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
259
260
                }
            }
261
262
263
264
            /* don't let SILK use more than 80% */
            if( st->silk_mode.bitRate > ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5 ) {
                st->silk_mode.bitRate = ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5;
            }
265
        }
266

267
268
269
270
271
272
273
274
275
276
277
        st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
        if (st->bandwidth == BANDWIDTH_NARROWBAND) {
            st->silk_mode.maxInternalSampleRate = 8000;
        } else if (st->bandwidth == BANDWIDTH_MEDIUMBAND) {
            st->silk_mode.maxInternalSampleRate = 12000;
        } else {
            SKP_assert( st->mode == MODE_HYBRID || st->bandwidth == BANDWIDTH_WIDEBAND );
            st->silk_mode.maxInternalSampleRate = 16000;
        }
        if( st->mode == MODE_HYBRID ) {
            /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
Koen Vos's avatar
Koen Vos committed
278
279
280
            st->silk_mode.minInternalSampleRate = 16000;
        } else {
            st->silk_mode.minInternalSampleRate = 8000;
281
        }
282

283
284
        /* Call SILK encoder for the low band */
        nBytes = max_data_bytes-1;
285
        if (prefill)
286
287
        {
            int zero=0;
288
        	SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, st->delay_buffer, st->encoder_buffer, NULL, &zero, 1 );
289
        }
290

Jean-Marc Valin's avatar
Jean-Marc Valin committed
291
        ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes, 0 );
292
293
294
295
        if( ret ) {
            fprintf (stderr, "SILK encode error: %d\n", ret);
            /* Handle error */
        }
296
297
298
        if (nBytes==0)
            return 0;

299
300
301
302
303
304
305
306
307
        /* Extract SILK internal bandwidth for signaling in first byte */
        if( st->mode == MODE_SILK_ONLY ) {
            if( st->silk_mode.internalSampleRate == 8000 ) {
                silk_internal_bandwidth = BANDWIDTH_NARROWBAND;
            } else if( st->silk_mode.internalSampleRate == 12000 ) {
                silk_internal_bandwidth = BANDWIDTH_MEDIUMBAND;
            } else if( st->silk_mode.internalSampleRate == 16000 ) {
                silk_internal_bandwidth = BANDWIDTH_WIDEBAND;
            }
308
309
        } else {
            SKP_assert( st->silk_mode.internalSampleRate == 16000 );
310
311
312
313
        }
    }

    /* CELT processing */
314
	{
315
	    int endband=21;
316

Jean-Marc Valin's avatar
Jean-Marc Valin committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
	    switch(st->bandwidth)
	    {
	    case BANDWIDTH_NARROWBAND:
	    	endband = 13;
	    	break;
	    case BANDWIDTH_WIDEBAND:
	    	endband = 17;
	    	break;
	    case BANDWIDTH_SUPERWIDEBAND:
	    	endband = 19;
	    	break;
	    case BANDWIDTH_FULLBAND:
	    	endband = 21;
	    	break;
	    }
	    celt_encoder_ctl(st->celt_enc, CELT_SET_END_BAND(endband));
333
	    celt_encoder_ctl(st->celt_enc, CELT_SET_CHANNELS(st->stream_channels));
334
335
336
	}
	if (st->mode != MODE_SILK_ONLY)
	{
Jean-Marc Valin's avatar
Jean-Marc Valin committed
337
338
        celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0));
        celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(510000));
339
340
        if (st->prev_mode == MODE_SILK_ONLY)
        {
341
        	unsigned char dummy[10];
342
        	celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
343
        	celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
344
        	celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(0));
345
        	/* FIXME: This wastes CPU a bit compared to just prefilling the buffer */
346
        	celt_encode(st->celt_enc, &st->delay_buffer[(st->encoder_buffer-st->delay_compensation-st->Fs/400)*st->channels], st->Fs/400, dummy, 10);
347
348
349
        } else {
        	celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(2));
        }
350

351
352
353
354
        if (st->mode == MODE_HYBRID)
        {
            int len;

355
            len = (ec_tell(&enc)+7)>>3;
356
            if( st->use_vbr ) {
Koen Vos's avatar
Koen Vos committed
357
                nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs);
358
359
360
361
362
            } else {
                /* check if SILK used up too much */
                nb_compr_bytes = len > bytes_target ? len : bytes_target;
            }
        } else {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
363
364
365
            if (st->use_vbr)
            {
                celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(1));
Jean-Marc Valin's avatar
Jean-Marc Valin committed
366
                celt_encoder_ctl(st->celt_enc, CELT_SET_VBR_CONSTRAINT(st->vbr_constraint));
Jean-Marc Valin's avatar
Jean-Marc Valin committed
367
368
369
370
371
                celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(st->bitrate_bps));
                nb_compr_bytes = max_data_bytes-1;
            } else {
                nb_compr_bytes = bytes_target;
            }
372
373
        }

374

375
        ec_enc_shrink(&enc, nb_compr_bytes);
376
377
378
	} else {
	    nb_compr_bytes = 0;
	}
Jean-Marc Valin's avatar
Jean-Marc Valin committed
379

380
381
382
383
384
385
386
387
388
389
    for (i=0;i<IMIN(frame_size, st->delay_compensation)*st->channels;i++)
        pcm_buf[i] = st->delay_buffer[(st->encoder_buffer-st->delay_compensation)*st->channels+i];
    for (;i<frame_size*st->channels;i++)
        pcm_buf[i] = pcm[i-st->delay_compensation*st->channels];
    if (st->mode != MODE_CELT_ONLY)
    {
        /* Check if we have a redundant 0-8 kHz band */
        ec_enc_bit_logp(&enc, redundancy, 12);
        if (redundancy)
        {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
390
            redundancy_bytes = st->stream_channels*st->bitrate_bps/1600;
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
            ec_enc_bit_logp(&enc, celt_to_silk, 1);
            if (st->mode == MODE_HYBRID)
            	ec_enc_uint(&enc, redundancy_bytes-2, 256);
        }
        start_band = 17;
    }

    if (st->mode == MODE_SILK_ONLY)
    {
        ret = (ec_tell(&enc)+7)>>3;
        ec_enc_done(&enc);
        nb_compr_bytes = ret;
    }

    /* 5 ms redundant frame for CELT->SILK */
    if (redundancy && celt_to_silk)
    {
        celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
Jean-Marc Valin's avatar
Jean-Marc Valin committed
409
        /* FIXME: That's OK for now, but we need to set the flags properly */
410
411
412
413
414
415
416
417
418
        celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0));
        celt_encode(st->celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes);
        celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
    }

    celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(start_band));

    if (st->mode != MODE_SILK_ONLY)
	{
419
	    /* Encode high band with CELT */
420
	    ret = celt_encode_with_ec(st->celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
421
422
	}

423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
    /* 5 ms redundant frame for SILK->CELT */
    if (redundancy && !celt_to_silk)
    {
        int N2, N4;
        N2 = st->Fs/200;
        N4 = st->Fs/400;

        celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
        celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
        celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(0));

        /* FIXME: Do proper prefilling here */
        celt_encode(st->celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, data+nb_compr_bytes, redundancy_bytes);

        celt_encode(st->celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes);
    }


    if (frame_size>st->encoder_buffer)
    {
    	for (i=0;i<st->encoder_buffer*st->channels;i++)
    		st->delay_buffer[i] = pcm[(frame_size-st->encoder_buffer)*st->channels+i];
    } else {
    	int tmp = st->encoder_buffer-frame_size;
    	for (i=0;i<tmp*st->channels;i++)
    		st->delay_buffer[i] = st->delay_buffer[i+frame_size*st->channels];
    	for (i=0;i<frame_size*st->channels;i++)
    		st->delay_buffer[tmp*st->channels+i] = pcm[i];
    }

453
454
455
456
457
458
459
460
461
462
463
	/* Signalling the mode in the first byte */
	data--;
	framerate = st->Fs/frame_size;
	period = 0;
	while (framerate < 400)
	{
	    framerate <<= 1;
	    period++;
	}
    if (st->mode == MODE_SILK_ONLY)
    {
464
        data[0] = (silk_internal_bandwidth-BANDWIDTH_NARROWBAND)<<5;
465
466
467
468
469
470
471
472
473
        data[0] |= (period-2)<<3;
    } else if (st->mode == MODE_CELT_ONLY)
    {
        int tmp = st->bandwidth-BANDWIDTH_MEDIUMBAND;
        if (tmp < 0)
            tmp = 0;
        data[0] = 0x80;
        data[0] |= tmp << 5;
        data[0] |= period<<3;
474
    } else /* Hybrid */
475
476
477
478
479
    {
        data[0] = 0x60;
        data[0] |= (st->bandwidth-BANDWIDTH_SUPERWIDEBAND)<<4;
        data[0] |= (period-2)<<3;
    }
480
    data[0] |= (st->stream_channels==2)<<2;
481
482
    /*printf ("%x\n", (int)data[0]);*/

Koen Vos's avatar
Koen Vos committed
483
484
485
#if OPUS_TEST_RANGE_CODER_STATE
    st->rangeFinal = enc.rng;
#endif
486
487
488
489
490
    if (to_celt)
        st->prev_mode = MODE_CELT_ONLY;
    else
        st->prev_mode = st->mode;
    return ret+1+redundancy_bytes;
491
}
492

493
int opus_encoder_ctl(OpusEncoder *st, int request, ...)
494
495
496
497
498
499
500
{
    va_list ap;

    va_start(ap, request);

    switch (request)
    {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
501
        case OPUS_SET_MODE_REQUEST:
502
503
        {
            int value = va_arg(ap, int);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
504
            st->user_mode = value;
505
506
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
507
        case OPUS_GET_MODE_REQUEST:
508
509
        {
            int *value = va_arg(ap, int*);
510
            *value = st->mode;
511
512
        }
        break;
513
514
515
516
517
518
519
520
521
522
523
524
        case OPUS_SET_BITRATE_REQUEST:
        {
            int value = va_arg(ap, int);
            st->bitrate_bps = value;
        }
        break;
        case OPUS_GET_BITRATE_REQUEST:
        {
            int *value = va_arg(ap, int*);
            *value = st->bitrate_bps;
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
525
        case OPUS_SET_BANDWIDTH_REQUEST:
526
527
        {
            int value = va_arg(ap, int);
528
529
530
531
            if (value < BANDWIDTH_AUTO || value > BANDWIDTH_FULLBAND)
            	return OPUS_BAD_ARG;
            st->user_bandwidth = value;
            if (st->user_bandwidth == BANDWIDTH_NARROWBAND) {
532
533
534
535
536
537
                st->silk_mode.maxInternalSampleRate = 8000;
            } else if (st->bandwidth == BANDWIDTH_MEDIUMBAND) {
                st->silk_mode.maxInternalSampleRate = 12000;
            } else {
                st->silk_mode.maxInternalSampleRate = 16000;
            }
538
539
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
540
        case OPUS_GET_BANDWIDTH_REQUEST:
541
542
543
544
545
        {
            int *value = va_arg(ap, int*);
            *value = st->bandwidth;
        }
        break;
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
        case OPUS_SET_DTX_FLAG_REQUEST:
        {
            int value = va_arg(ap, int);
            st->silk_mode.useDTX = value;
        }
        break;
        case OPUS_GET_DTX_FLAG_REQUEST:
        {
            int *value = va_arg(ap, int*);
            *value = st->silk_mode.useDTX;
        }
        break;
        case OPUS_SET_COMPLEXITY_REQUEST:
        {
            int value = va_arg(ap, int);
            st->silk_mode.complexity = value;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
562
            celt_encoder_ctl(st->celt_enc, CELT_SET_COMPLEXITY(value));
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
        }
        break;
        case OPUS_GET_COMPLEXITY_REQUEST:
        {
            int *value = va_arg(ap, int*);
            *value = st->silk_mode.complexity;
        }
        break;
        case OPUS_SET_INBAND_FEC_FLAG_REQUEST:
        {
            int value = va_arg(ap, int);
            st->silk_mode.useInBandFEC = value;
        }
        break;
        case OPUS_GET_INBAND_FEC_FLAG_REQUEST:
        {
            int *value = va_arg(ap, int*);
            *value = st->silk_mode.useInBandFEC;
        }
        break;
        case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
        {
            int value = va_arg(ap, int);
            st->silk_mode.packetLossPercentage = value;
        }
        break;
        case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
        {
            int *value = va_arg(ap, int*);
            *value = st->silk_mode.packetLossPercentage;
        }
        break;
        case OPUS_SET_VBR_FLAG_REQUEST:
596
597
        {
            int value = va_arg(ap, int);
598
599
            st->use_vbr = value;
            st->silk_mode.useCBR = 1-value;
600
601
        }
        break;
602
        case OPUS_GET_VBR_FLAG_REQUEST:
603
604
        {
            int *value = va_arg(ap, int*);
605
            *value = st->use_vbr;
606
607
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
608
609
610
        case OPUS_SET_VOICE_RATIO_REQUEST:
        {
            int value = va_arg(ap, int);
Jean-Marc Valin's avatar
Cleanup    
Jean-Marc Valin committed
611
612
            if (value>100 || value<0)
                return OPUS_BAD_ARG;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
613
614
615
616
617
618
619
620
621
            st->voice_ratio = value;
        }
        break;
        case OPUS_GET_VOICE_RATIO_REQUEST:
        {
            int *value = va_arg(ap, int*);
            *value = st->voice_ratio;
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
622
623
624
625
626
627
628
629
630
631
632
633
        case OPUS_SET_VBR_CONSTRAINT_REQUEST:
        {
            int value = va_arg(ap, int);
            st->vbr_constraint = value;
        }
        break;
        case OPUS_GET_VBR_CONSTRAINT_REQUEST:
        {
            int *value = va_arg(ap, int*);
            *value = st->vbr_constraint;
        }
        break;
634
        default:
Jean-Marc Valin's avatar
Jean-Marc Valin committed
635
            fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);
636
            break;
637
    }
Alfred E. Heggestad's avatar
Alfred E. Heggestad committed
638
639

    va_end(ap);
640
    return OPUS_OK;
641
642
}

Jean-Marc Valin's avatar
Jean-Marc Valin committed
643
void opus_encoder_destroy(OpusEncoder *st)
644
645
646
{
	free(st);
}
647

Koen Vos's avatar
Koen Vos committed
648
649
650
651
652
653
#if OPUS_TEST_RANGE_CODER_STATE
int opus_encoder_get_final_range(OpusEncoder *st)
{
    return st->rangeFinal;
}
#endif