opus_encoder.c 14.2 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>
Jean-Marc Valin's avatar
Jean-Marc Valin committed
35
#include "opus_encoder.h"
Jean-Marc Valin's avatar
Jean-Marc Valin committed
36
37
#include "entenc.h"
#include "modes.h"
38
#include "SKP_Silk_SDK_API.h"
39

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

46
    /* Create SILK encoder */
47
    ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes );
48
49
50
    if( ret ) {
    	/* Handle error */
    }
Jean-Marc Valin's avatar
Jean-Marc Valin committed
51
    celtEncSizeBytes = celt_encoder_get_size(channels);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
52
53
54
55
    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);
56
    st->stream_channels = st->channels = channels;
57
58

    st->Fs = Fs;
59

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

65
66
67
68
69
70
71
72
    /* 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
73
    st->silk_mode.complexity            = 10;
74

75
    /* Create CELT encoder */
76
	/* Initialize CELT encoder */
77
	st->celt_enc = celt_encoder_init(st->celt_enc, Fs, channels, NULL);
78

79
80
	st->mode = MODE_HYBRID;
	st->bandwidth = BANDWIDTH_FULLBAND;
81
82
	st->use_vbr = 0;
	st->bitrate_bps = 32000;
83

84
85
86
	return st;
}

Jean-Marc Valin's avatar
Jean-Marc Valin committed
87
int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
88
		unsigned char *data, int max_data_bytes)
89
{
90
    int i;
91
	int ret=0;
92
	SKP_int32 nBytes;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
93
	ec_enc enc;
94
	int framerate, period;
95
96
    int silk_internal_bandwidth;
    int bytes_target;
97
    int prefill=0;
98
99
    int start_band;
    int redundancy = 0;
100
101

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

103
	data += 1;
104
105
106
107
	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);
108
		prefill=1;
109
110
	}

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

113
	/* SILK processing */
114
115
    if (st->mode != MODE_CELT_ONLY)
    {
116
117
        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
118
119
120
            if( st->bandwidth == BANDWIDTH_SUPERWIDEBAND ) {
                if( st->Fs == 100 * frame_size ) {
                    /* 24 kHz, 10 ms */
Koen Vos's avatar
Koen Vos committed
121
                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 2000 + st->use_vbr * 1000 ) * 2 ) / 3;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
122
123
                } else {
                    /* 24 kHz, 20 ms */
Koen Vos's avatar
Koen Vos committed
124
                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 1000 + st->use_vbr * 1000 ) * 2 ) / 3;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
125
126
127
128
                }
            } else {
                if( st->Fs == 100 * frame_size ) {
                    /* 48 kHz, 10 ms */
Koen Vos's avatar
Koen Vos committed
129
                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 8000 + st->use_vbr * 3000 ) / 2;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
130
131
                } else {
                    /* 48 kHz, 20 ms */
Koen Vos's avatar
Koen Vos committed
132
                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 9000 + st->use_vbr * 1000 ) / 2;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
133
134
                }
            }
135
136
137
138
            /* 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;
            }
139
        }
140

141
142
143
144
145
146
147
148
149
150
151
        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
152
153
154
            st->silk_mode.minInternalSampleRate = 16000;
        } else {
            st->silk_mode.minInternalSampleRate = 8000;
155
        }
156

157
158
        /* Call SILK encoder for the low band */
        nBytes = max_data_bytes-1;
159
        if (prefill)
160
161
162
163
        {
            int zero=0;
        	SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, st->delay_buffer, ENCODER_BUFFER, NULL, &zero, 1 );
        }
164

Jean-Marc Valin's avatar
Jean-Marc Valin committed
165
        ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes, 0 );
166
167
168
169
170
171
172
173
174
175
176
177
178
        if( ret ) {
            fprintf (stderr, "SILK encode error: %d\n", ret);
            /* Handle error */
        }
        /* 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;
            }
179
180
        } else {
            SKP_assert( st->silk_mode.internalSampleRate == 16000 );
181
182
183
184
185
        }
    }

    /* CELT processing */
	if (st->mode != MODE_SILK_ONLY)
186
	{
Jean-Marc Valin's avatar
Jean-Marc Valin committed
187
	    int endband;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
188
	    short pcm_buf[960*2];
189
	    int nb_compr_bytes;
190

Jean-Marc Valin's avatar
Jean-Marc Valin committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
	    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));
207
	    celt_encoder_ctl(st->celt_enc, CELT_SET_CHANNELS(st->stream_channels));
208

Jean-Marc Valin's avatar
Jean-Marc Valin committed
209
210
        celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0));
        celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(510000));
211
212
        if (st->prev_mode == MODE_SILK_ONLY)
        {
213
        	unsigned char dummy[2];
214
215
        	celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
        	celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(0));
216
217
        	/* FIXME: This wastes CPU a bit compared to just prefilling the buffer */
        	celt_encode(st->celt_enc, &st->delay_buffer[(ENCODER_BUFFER-ENCODER_DELAY_COMPENSATION-120)*st->channels], 120, dummy, 10);
218
219
220
        } else {
        	celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(2));
        }
221
222
223
224
225
226
227
228
229
230
231

        start_band = 0;
        if (st->mode == MODE_HYBRID)
        {
            /* Check if we have a redundant 0-8 kHz band */
            ec_enc_bit_logp(&enc, redundancy, 12);
            if (!redundancy)
                start_band = 17;
        }
        celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(start_band));

232
233
234
235
        if (st->mode == MODE_HYBRID)
        {
            int len;

236
            len = (ec_tell(&enc)+7)>>3;
237
            if( st->use_vbr ) {
Koen Vos's avatar
Koen Vos committed
238
                nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs);
239
240
241
242
243
            } 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
244
245
246
247
248
249
250
251
            if (st->use_vbr)
            {
                celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(1));
                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;
            }
252
253
        }

254
        for (i=0;i<IMIN(frame_size, ENCODER_DELAY_COMPENSATION)*st->channels;i++)
255
            pcm_buf[i] = st->delay_buffer[(ENCODER_BUFFER-ENCODER_DELAY_COMPENSATION)*st->channels+i];
Jean-Marc Valin's avatar
Jean-Marc Valin committed
256
257
        for (;i<frame_size*st->channels;i++)
            pcm_buf[i] = pcm[i-ENCODER_DELAY_COMPENSATION*st->channels];
258

259
        ec_enc_shrink(&enc, nb_compr_bytes);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
260

261
	    /* Encode high band with CELT */
262
	    ret = celt_encode_with_ec(st->celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
263

264
	    if (frame_size>ENCODER_BUFFER)
265
	    {
266
267
	        for (i=0;i<ENCODER_BUFFER*st->channels;i++)
	            st->delay_buffer[i] = pcm[(frame_size-ENCODER_BUFFER)*st->channels+i];
268
	    } else {
269
	        int tmp = ENCODER_BUFFER-frame_size;
270
271
272
273
274
	        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];
	    }
275
	} else {
276
	    ret = (ec_tell(&enc)+7)>>3;
277
278
279
	    ec_enc_done(&enc);
	}

280
281
282
283
284
285
286
287
288
289
290
	/* 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)
    {
291
        data[0] = (silk_internal_bandwidth-BANDWIDTH_NARROWBAND)<<5;
292
293
294
295
296
297
298
299
300
        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;
301
    } else /* Hybrid */
302
303
304
305
306
    {
        data[0] = 0x60;
        data[0] |= (st->bandwidth-BANDWIDTH_SUPERWIDEBAND)<<4;
        data[0] |= (period-2)<<3;
    }
307
    data[0] |= (st->stream_channels==2)<<2;
308
309
    /*printf ("%x\n", (int)data[0]);*/

Koen Vos's avatar
Koen Vos committed
310
311
312
#if OPUS_TEST_RANGE_CODER_STATE
    st->rangeFinal = enc.rng;
#endif
313
    st->prev_mode = st->mode;
314
    return ret+1;
315
}
316

Jean-Marc Valin's avatar
Jean-Marc Valin committed
317
void opus_encoder_ctl(OpusEncoder *st, int request, ...)
318
319
320
321
322
323
324
{
    va_list ap;

    va_start(ap, request);

    switch (request)
    {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
325
        case OPUS_SET_MODE_REQUEST:
326
327
328
329
330
        {
            int value = va_arg(ap, int);
            st->mode = value;
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
331
        case OPUS_GET_MODE_REQUEST:
332
333
334
335
336
        {
            int *value = va_arg(ap, int*);
            *value = st->mode;
        }
        break;
337
338
339
340
341
342
343
344
345
346
347
348
        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
349
        case OPUS_SET_BANDWIDTH_REQUEST:
350
351
352
        {
            int value = va_arg(ap, int);
            st->bandwidth = value;
353
354
355
356
357
358
359
            if (st->bandwidth == BANDWIDTH_NARROWBAND) {
                st->silk_mode.maxInternalSampleRate = 8000;
            } else if (st->bandwidth == BANDWIDTH_MEDIUMBAND) {
                st->silk_mode.maxInternalSampleRate = 12000;
            } else {
                st->silk_mode.maxInternalSampleRate = 16000;
            }
360
361
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
362
        case OPUS_GET_BANDWIDTH_REQUEST:
363
364
365
366
367
        {
            int *value = va_arg(ap, int*);
            *value = st->bandwidth;
        }
        break;
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
        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
384
            celt_encoder_ctl(st->celt_enc, CELT_SET_COMPLEXITY(value));
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
        }
        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:
418
419
        {
            int value = va_arg(ap, int);
420
421
            st->use_vbr = value;
            st->silk_mode.useCBR = 1-value;
422
423
        }
        break;
424
        case OPUS_GET_VBR_FLAG_REQUEST:
425
426
        {
            int *value = va_arg(ap, int*);
427
            *value = st->use_vbr;
428
429
430
        }
        break;
        default:
Jean-Marc Valin's avatar
Jean-Marc Valin committed
431
            fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);
432
            break;
433
    }
Alfred E. Heggestad's avatar
Alfred E. Heggestad committed
434
435

    va_end(ap);
436
437
}

Jean-Marc Valin's avatar
Jean-Marc Valin committed
438
void opus_encoder_destroy(OpusEncoder *st)
439
440
441
{
	free(st);
}
442

Koen Vos's avatar
Koen Vos committed
443
444
445
446
447
448
#if OPUS_TEST_RANGE_CODER_STATE
int opus_encoder_get_final_range(OpusEncoder *st)
{
    return st->rangeFinal;
}
#endif