opus_encoder.c 12.5 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
33
34
35
36
/*
   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.

   - Neither the name of the Xiph.org Foundation nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

   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>
37
#include <stdio.h>
38
#include <stdarg.h>
Jean-Marc Valin's avatar
Jean-Marc Valin committed
39
#include "opus_encoder.h"
Jean-Marc Valin's avatar
Jean-Marc Valin committed
40
41
#include "entenc.h"
#include "modes.h"
42
#include "SKP_Silk_SDK_API.h"
43

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

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

    st->Fs = Fs;
63

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

69
70
71
72
73
74
75
76
    /* 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
77
    st->silk_mode.complexity            = 10;
78

79
    /* Create CELT encoder */
80
	/* Initialize CELT encoder */
81
	st->celt_enc = celt_encoder_init(st->celt_enc, Fs, channels, NULL);
82

83
84
	st->mode = MODE_HYBRID;
	st->bandwidth = BANDWIDTH_FULLBAND;
85
86
	st->use_vbr = 0;
	st->bitrate_bps = 32000;
87

88
89
90
	return st;
}

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

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

105
	data += 1;
106
	ec_byte_writeinit_buffer(&buf, data, max_data_bytes-1);
107
	ec_enc_init(&enc,&buf);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
108

109
	/* SILK processing */
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
110
    if (st->mode != MODE_CELT_ONLY) {
111
112
        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
113
114
115
            if( st->bandwidth == BANDWIDTH_SUPERWIDEBAND ) {
                if( st->Fs == 100 * frame_size ) {
                    /* 24 kHz, 10 ms */
116
                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 12000 - ( 1 - st->use_vbr ) * 10000 ) * 2 ) / 3;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
117
118
                } else {
                    /* 24 kHz, 20 ms */
119
                    st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 8000 - ( 1 - st->use_vbr ) * 7000 ) * 2 ) / 3;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
120
121
122
123
                }
            } else {
                if( st->Fs == 100 * frame_size ) {
                    /* 48 kHz, 10 ms */
124
                    st->silk_mode.bitRate = ( st->silk_mode.bitRate + 16000 - ( 1 - st->use_vbr ) * 8000 ) / 2;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
125
126
                } else {
                    /* 48 kHz, 20 ms */
127
                	st->silk_mode.bitRate = ( st->silk_mode.bitRate + 14000 - ( 1 - st->use_vbr ) * 5000 ) / 2;
Karsten Vandborg Sorensen's avatar
Karsten Vandborg Sorensen committed
128
129
                }
            }
130
        }
131

132
133
134
135
136
137
138
139
140
141
142
143
144
        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 */
            st->silk_mode.minInternalSampleRate = st->silk_mode.maxInternalSampleRate ;
        }
145

146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
        /* Call SILK encoder for the low band */
        nBytes = max_data_bytes-1;
        ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes );
        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;
            }
        }
    }

    /* CELT processing */
	if (st->mode != MODE_SILK_ONLY)
167
	{
Jean-Marc Valin's avatar
Jean-Marc Valin committed
168
		int endband;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
169
	    short pcm_buf[960*2];
170
	    int nb_compr_bytes;
171

Jean-Marc Valin's avatar
Jean-Marc Valin committed
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
	    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));
188
	    celt_encoder_ctl(st->celt_enc, CELT_SET_CHANNELS(st->stream_channels));
189

Jean-Marc Valin's avatar
Jean-Marc Valin committed
190
191
        celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0));
        celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(510000));
192
193
194
195
196
197
198
199
200
201
202
203
204
205
        if (st->mode == MODE_HYBRID)
        {
            int len;
            celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(17));

            len = (ec_enc_tell(&enc, 0)+7)>>3;
            if( st->use_vbr ) {
                nb_compr_bytes = len + (st->bitrate_bps - 12000) * frame_size / (2 * 8 * st->Fs);
            } else {
                /* check if SILK used up too much */
                nb_compr_bytes = len > bytes_target ? len : bytes_target;
            }
        } else {
            celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
Jean-Marc Valin's avatar
Jean-Marc Valin committed
206
207
208
209
210
211
212
213
            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;
            }
214
215
        }

Jean-Marc Valin's avatar
Jean-Marc Valin committed
216
	    for (i=0;i<ENCODER_DELAY_COMPENSATION*st->channels;i++)
Jean-Marc Valin's avatar
Jean-Marc Valin committed
217
	        pcm_buf[i] = st->delay_buffer[i];
Jean-Marc Valin's avatar
Jean-Marc Valin committed
218
219
        for (;i<frame_size*st->channels;i++)
            pcm_buf[i] = pcm[i-ENCODER_DELAY_COMPENSATION*st->channels];
220

221
        ec_byte_shrink(&buf, nb_compr_bytes);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
222

223
	    /* Encode high band with CELT */
224
	    ret = celt_encode_with_ec(st->celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
Jean-Marc Valin's avatar
Jean-Marc Valin committed
225
226
	    for (i=0;i<ENCODER_DELAY_COMPENSATION*st->channels;i++)
	        st->delay_buffer[i] = pcm[frame_size*st->channels-ENCODER_DELAY_COMPENSATION*st->channels+i];
227
	} else {
228
	    ret = (ec_enc_tell(&enc, 0)+7)>>3;
229
230
231
	    ec_enc_done(&enc);
	}

232
233
234
235
236
237
238
239
240
241
242
	/* 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)
    {
243
        data[0] = (silk_internal_bandwidth-BANDWIDTH_NARROWBAND)<<5;
244
245
246
247
248
249
250
251
252
        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;
253
    } else /* Hybrid */
254
255
256
257
258
    {
        data[0] = 0x60;
        data[0] |= (st->bandwidth-BANDWIDTH_SUPERWIDEBAND)<<4;
        data[0] |= (period-2)<<3;
    }
259
    data[0] |= (st->stream_channels==2)<<2;
260
261
    /*printf ("%x\n", (int)data[0]);*/

Koen Vos's avatar
Koen Vos committed
262
263
264
265
#if OPUS_TEST_RANGE_CODER_STATE
    st->rangeFinal = enc.rng;
#endif

266
    return ret+1;
267
}
268

Jean-Marc Valin's avatar
Jean-Marc Valin committed
269
void opus_encoder_ctl(OpusEncoder *st, int request, ...)
270
271
272
273
274
275
276
{
    va_list ap;

    va_start(ap, request);

    switch (request)
    {
Jean-Marc Valin's avatar
Jean-Marc Valin committed
277
        case OPUS_SET_MODE_REQUEST:
278
279
280
281
282
        {
            int value = va_arg(ap, int);
            st->mode = value;
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
283
        case OPUS_GET_MODE_REQUEST:
284
285
286
287
288
        {
            int *value = va_arg(ap, int*);
            *value = st->mode;
        }
        break;
289
290
291
292
293
294
295
296
297
298
299
300
        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
301
        case OPUS_SET_BANDWIDTH_REQUEST:
302
303
304
        {
            int value = va_arg(ap, int);
            st->bandwidth = value;
305
306
307
308
309
310
311
            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;
            }
312
313
        }
        break;
Jean-Marc Valin's avatar
Jean-Marc Valin committed
314
        case OPUS_GET_BANDWIDTH_REQUEST:
315
316
317
318
319
        {
            int *value = va_arg(ap, int*);
            *value = st->bandwidth;
        }
        break;
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
        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;
        }
        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:
369
370
        {
            int value = va_arg(ap, int);
371
372
            st->use_vbr = value;
            st->silk_mode.useCBR = 1-value;
373
374
        }
        break;
375
        case OPUS_GET_VBR_FLAG_REQUEST:
376
377
        {
            int *value = va_arg(ap, int*);
378
            *value = st->use_vbr;
379
380
381
        }
        break;
        default:
Jean-Marc Valin's avatar
Jean-Marc Valin committed
382
            fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);
383
            break;
384
    }
Alfred E. Heggestad's avatar
Alfred E. Heggestad committed
385
386

    va_end(ap);
387
388
}

Jean-Marc Valin's avatar
Jean-Marc Valin committed
389
void opus_encoder_destroy(OpusEncoder *st)
390
391
392
{
	free(st);
}
393

Koen Vos's avatar
Koen Vos committed
394
395
396
397
398
399
#if OPUS_TEST_RANGE_CODER_STATE
int opus_encoder_get_final_range(OpusEncoder *st)
{
    return st->rangeFinal;
}
#endif