Simple mode selection logic
[opus.git] / src / opus_encoder.c
1 /* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
2    Written by Jean-Marc Valin and Koen Vos */
3 /*
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
15    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
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <stdarg.h>
35 #include "opus_encoder.h"
36 #include "entenc.h"
37 #include "modes.h"
38 #include "SKP_Silk_SDK_API.h"
39
40 OpusEncoder *opus_encoder_create(int Fs, int channels)
41 {
42     int err;
43     char *raw_state;
44         OpusEncoder *st;
45         int ret, silkEncSizeBytes, celtEncSizeBytes;
46
47     /* Create SILK encoder */
48     ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes );
49     if( ret ) {
50         /* Handle error */
51     }
52     celtEncSizeBytes = celt_encoder_get_size(channels);
53     raw_state = calloc(sizeof(OpusEncoder)+silkEncSizeBytes+celtEncSizeBytes, 1);
54     st = (OpusEncoder*)raw_state;
55     st->silk_enc = (void*)(raw_state+sizeof(OpusEncoder));
56     st->celt_enc = (CELTEncoder*)(raw_state+sizeof(OpusEncoder)+silkEncSizeBytes);
57     st->stream_channels = st->channels = channels;
58
59     st->Fs = Fs;
60
61     ret = SKP_Silk_SDK_InitEncoder( st->silk_enc, &st->silk_mode );
62     if( ret ) {
63         /* Handle error */
64     }
65
66     /* default SILK parameters */
67     st->silk_mode.API_sampleRate        = st->Fs;
68     st->silk_mode.maxInternalSampleRate = 16000;
69     st->silk_mode.minInternalSampleRate = 8000;
70     st->silk_mode.payloadSize_ms        = 20;
71     st->silk_mode.packetLossPercentage  = 0;
72     st->silk_mode.useInBandFEC          = 0;
73     st->silk_mode.useDTX                = 0;
74     st->silk_mode.complexity            = 10;
75
76     /* Create CELT encoder */
77         /* Initialize CELT encoder */
78         st->celt_enc = celt_encoder_init(st->celt_enc, Fs, channels, &err);
79
80         st->mode = MODE_HYBRID;
81         st->bandwidth = BANDWIDTH_FULLBAND;
82         st->use_vbr = 0;
83         st->bitrate_bps = 32000;
84         st->user_mode = OPUS_MODE_AUTO;
85         st->voice_ratio = 90;
86
87         st->encoder_buffer = st->Fs/100;
88         st->delay_compensation = st->Fs/400;
89         if (st->Fs > 16000)
90                 st->delay_compensation += 10;
91         return st;
92 }
93
94 int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
95                 unsigned char *data, int max_data_bytes)
96 {
97     int i;
98         int ret=0;
99         SKP_int32 nBytes;
100         ec_enc enc;
101         int framerate, period;
102     int silk_internal_bandwidth;
103     int bytes_target;
104     int prefill=0;
105     int start_band = 0;
106     int redundancy = 0;
107     int redundancy_bytes = 0;
108     int celt_to_silk = 0;
109     short pcm_buf[960*2];
110     int nb_compr_bytes;
111     int to_celt = 0;
112     celt_int32 mono_rate;
113
114     if (st->channels == 2)
115     {
116         celt_int32 decision_rate;
117         decision_rate = st->bitrate_bps + st->voice_ratio*st->voice_ratio;
118         if (st->stream_channels == 2)
119             decision_rate += 4000;
120         else
121             decision_rate -= 4000;
122         if (decision_rate>48000)
123             st->stream_channels = 2;
124         else
125             st->stream_channels = 1;
126     } else {
127         st->stream_channels = 1;
128     }
129     /* Equivalent bit-rate for mono */
130     mono_rate = st->bitrate_bps;
131     if (st->stream_channels==2)
132         mono_rate = (mono_rate+10000)/2;
133
134     /* Mode selection */
135     if (st->user_mode==OPUS_MODE_AUTO)
136     {
137         celt_int32 decision_rate;
138         decision_rate = mono_rate - 3*st->voice_ratio*st->voice_ratio;
139         if (st->prev_mode == MODE_CELT_ONLY)
140             decision_rate += 4000;
141         else if (st->prev_mode>0)
142             decision_rate -= 4000;
143         if (decision_rate>24000)
144             st->mode = MODE_CELT_ONLY;
145         else
146             st->mode = MODE_SILK_ONLY;
147     } else if (st->user_mode==OPUS_MODE_VOICE)
148     {
149         st->mode = MODE_SILK_ONLY;
150     } else {/* OPUS_AUDIO_MODE */
151         st->mode = MODE_CELT_ONLY;
152     }
153
154     /* FIXME: Remove this once SILK supports stereo */
155     if (st->channels == 2)
156         st->mode = MODE_CELT_ONLY;
157
158     /* Bandwidth selection */
159     if (st->mode == MODE_CELT_ONLY)
160     {
161         if (mono_rate>35000 || (mono_rate>28000 && st->bandwidth==BANDWIDTH_FULLBAND))
162             st->bandwidth = BANDWIDTH_FULLBAND;
163         else if (mono_rate>28000 || (mono_rate>24000 && st->bandwidth==BANDWIDTH_SUPERWIDEBAND))
164             st->bandwidth = BANDWIDTH_SUPERWIDEBAND;
165         else if (mono_rate>24000 || (mono_rate>18000 && st->bandwidth==BANDWIDTH_WIDEBAND))
166             st->bandwidth = BANDWIDTH_WIDEBAND;
167         else
168             st->bandwidth = BANDWIDTH_NARROWBAND;
169     } else {
170         if (mono_rate>28000 || (mono_rate>24000 && st->bandwidth==BANDWIDTH_FULLBAND))
171             st->bandwidth = BANDWIDTH_FULLBAND;
172         else if (mono_rate>24000 || (mono_rate>18000 && st->bandwidth==BANDWIDTH_SUPERWIDEBAND))
173             st->bandwidth = BANDWIDTH_SUPERWIDEBAND;
174         else if (mono_rate>18000 || (mono_rate>14000 && st->bandwidth==BANDWIDTH_WIDEBAND))
175             st->bandwidth = BANDWIDTH_WIDEBAND;
176         else if (mono_rate>14000 || (mono_rate>11000 && st->bandwidth==BANDWIDTH_MEDIUMBAND))
177             st->bandwidth = BANDWIDTH_MEDIUMBAND;
178         else
179             st->bandwidth = BANDWIDTH_NARROWBAND;
180     }
181     /* Preventing non-sensical configurations */
182     if (frame_size < st->Fs/100 && st->mode != MODE_CELT_ONLY)
183         st->mode = MODE_CELT_ONLY;
184     if (frame_size > st->Fs/50 && st->mode != MODE_SILK_ONLY)
185         st->mode = MODE_SILK_ONLY;
186     if (st->mode == MODE_CELT_ONLY && st->bandwidth == BANDWIDTH_MEDIUMBAND)
187         st->bandwidth = BANDWIDTH_WIDEBAND;
188     if (st->mode == MODE_SILK_ONLY && st->bandwidth > BANDWIDTH_WIDEBAND)
189         st->mode = MODE_HYBRID;
190     if (st->mode == MODE_HYBRID && st->bandwidth <= BANDWIDTH_WIDEBAND)
191         st->mode = MODE_SILK_ONLY;
192
193     printf("%d %d %d\n", st->stream_channels, st->mode, st->bandwidth);
194
195         bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1;
196
197         data += 1;
198         if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
199         {
200                 SKP_SILK_SDK_EncControlStruct dummy;
201                 SKP_Silk_SDK_InitEncoder( st->silk_enc, &dummy);
202                 prefill=1;
203         }
204         if (st->prev_mode >0 &&
205                 ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
206                 || (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)))
207         {
208             redundancy = 1;
209             celt_to_silk = (st->mode != MODE_CELT_ONLY);
210             if (!celt_to_silk)
211             {
212                 /* Switch to SILK/hybrid if frame size is 10 ms or more*/
213                 if (frame_size >= st->Fs/100)
214                 {
215                         st->mode = st->prev_mode;
216                         to_celt = 1;
217                 } else {
218                         redundancy=0;
219                 }
220             }
221         }
222
223         ec_enc_init(&enc, data, max_data_bytes-1);
224
225         /* SILK processing */
226     if (st->mode != MODE_CELT_ONLY)
227     {
228         st->silk_mode.bitRate = st->bitrate_bps - 8*st->Fs/frame_size;
229         if( st->mode == MODE_HYBRID ) {
230             if( st->bandwidth == BANDWIDTH_SUPERWIDEBAND ) {
231                 if( st->Fs == 100 * frame_size ) {
232                     /* 24 kHz, 10 ms */
233                     st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 2000 + st->use_vbr * 1000 ) * 2 ) / 3;
234                 } else {
235                     /* 24 kHz, 20 ms */
236                     st->silk_mode.bitRate = ( ( st->silk_mode.bitRate + 1000 + st->use_vbr * 1000 ) * 2 ) / 3;
237                 }
238             } else {
239                 if( st->Fs == 100 * frame_size ) {
240                     /* 48 kHz, 10 ms */
241                     st->silk_mode.bitRate = ( st->silk_mode.bitRate + 8000 + st->use_vbr * 3000 ) / 2;
242                 } else {
243                     /* 48 kHz, 20 ms */
244                     st->silk_mode.bitRate = ( st->silk_mode.bitRate + 9000 + st->use_vbr * 1000 ) / 2;
245                 }
246             }
247             /* don't let SILK use more than 80% */
248             if( st->silk_mode.bitRate > ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5 ) {
249                 st->silk_mode.bitRate = ( st->bitrate_bps - 8*st->Fs/frame_size ) * 4/5;
250             }
251         }
252
253         st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
254         if (st->bandwidth == BANDWIDTH_NARROWBAND) {
255             st->silk_mode.maxInternalSampleRate = 8000;
256         } else if (st->bandwidth == BANDWIDTH_MEDIUMBAND) {
257             st->silk_mode.maxInternalSampleRate = 12000;
258         } else {
259             SKP_assert( st->mode == MODE_HYBRID || st->bandwidth == BANDWIDTH_WIDEBAND );
260             st->silk_mode.maxInternalSampleRate = 16000;
261         }
262         if( st->mode == MODE_HYBRID ) {
263             /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
264             st->silk_mode.minInternalSampleRate = 16000;
265         } else {
266             st->silk_mode.minInternalSampleRate = 8000;
267         }
268
269         /* Call SILK encoder for the low band */
270         nBytes = max_data_bytes-1;
271         if (prefill)
272         {
273             int zero=0;
274                 SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, st->delay_buffer, st->encoder_buffer, NULL, &zero, 1 );
275         }
276
277         ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes, 0 );
278         if( ret ) {
279             fprintf (stderr, "SILK encode error: %d\n", ret);
280             /* Handle error */
281         }
282         /* Extract SILK internal bandwidth for signaling in first byte */
283         if( st->mode == MODE_SILK_ONLY ) {
284             if( st->silk_mode.internalSampleRate == 8000 ) {
285                 silk_internal_bandwidth = BANDWIDTH_NARROWBAND;
286             } else if( st->silk_mode.internalSampleRate == 12000 ) {
287                 silk_internal_bandwidth = BANDWIDTH_MEDIUMBAND;
288             } else if( st->silk_mode.internalSampleRate == 16000 ) {
289                 silk_internal_bandwidth = BANDWIDTH_WIDEBAND;
290             }
291         } else {
292             SKP_assert( st->silk_mode.internalSampleRate == 16000 );
293         }
294     }
295
296     /* CELT processing */
297         {
298             int endband=21;
299
300             switch(st->bandwidth)
301             {
302             case BANDWIDTH_NARROWBAND:
303                 endband = 13;
304                 break;
305             case BANDWIDTH_WIDEBAND:
306                 endband = 17;
307                 break;
308             case BANDWIDTH_SUPERWIDEBAND:
309                 endband = 19;
310                 break;
311             case BANDWIDTH_FULLBAND:
312                 endband = 21;
313                 break;
314             }
315             celt_encoder_ctl(st->celt_enc, CELT_SET_END_BAND(endband));
316             celt_encoder_ctl(st->celt_enc, CELT_SET_CHANNELS(st->stream_channels));
317         }
318         if (st->mode != MODE_SILK_ONLY)
319         {
320         celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0));
321         celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(510000));
322         if (st->prev_mode == MODE_SILK_ONLY)
323         {
324                 unsigned char dummy[10];
325                 celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
326                 celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
327                 celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(0));
328                 /* FIXME: This wastes CPU a bit compared to just prefilling the buffer */
329                 celt_encode(st->celt_enc, &st->delay_buffer[(st->encoder_buffer-st->delay_compensation-st->Fs/400)*st->channels], st->Fs/400, dummy, 10);
330         } else {
331                 celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(2));
332         }
333
334         if (st->mode == MODE_HYBRID)
335         {
336             int len;
337
338             len = (ec_tell(&enc)+7)>>3;
339             if( st->use_vbr ) {
340                 nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs);
341             } else {
342                 /* check if SILK used up too much */
343                 nb_compr_bytes = len > bytes_target ? len : bytes_target;
344             }
345         } else {
346             if (st->use_vbr)
347             {
348                 celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(1));
349                 celt_encoder_ctl(st->celt_enc, CELT_SET_BITRATE(st->bitrate_bps));
350                 nb_compr_bytes = max_data_bytes-1;
351             } else {
352                 nb_compr_bytes = bytes_target;
353             }
354         }
355
356
357         ec_enc_shrink(&enc, nb_compr_bytes);
358         } else {
359             nb_compr_bytes = 0;
360         }
361
362     for (i=0;i<IMIN(frame_size, st->delay_compensation)*st->channels;i++)
363         pcm_buf[i] = st->delay_buffer[(st->encoder_buffer-st->delay_compensation)*st->channels+i];
364     for (;i<frame_size*st->channels;i++)
365         pcm_buf[i] = pcm[i-st->delay_compensation*st->channels];
366     if (st->mode != MODE_CELT_ONLY)
367     {
368         /* Check if we have a redundant 0-8 kHz band */
369         ec_enc_bit_logp(&enc, redundancy, 12);
370         if (redundancy)
371         {
372             redundancy_bytes = 40;
373             ec_enc_bit_logp(&enc, celt_to_silk, 1);
374             if (st->mode == MODE_HYBRID)
375                 ec_enc_uint(&enc, redundancy_bytes-2, 256);
376         }
377         start_band = 17;
378     }
379
380     if (st->mode == MODE_SILK_ONLY)
381     {
382         ret = (ec_tell(&enc)+7)>>3;
383         ec_enc_done(&enc);
384         nb_compr_bytes = ret;
385     }
386
387     /* 5 ms redundant frame for CELT->SILK */
388     if (redundancy && celt_to_silk)
389     {
390         celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
391         /* FIXME: This is wrong -- we need to set the flags properly */
392         celt_encoder_ctl(st->celt_enc, CELT_SET_VBR(0));
393         /* FIXME: Make sure not to overflow here */
394         celt_encode(st->celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes);
395         celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
396     }
397
398     celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(start_band));
399
400     if (st->mode != MODE_SILK_ONLY)
401         {
402             /* Encode high band with CELT */
403             ret = celt_encode_with_ec(st->celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
404         }
405
406     /* 5 ms redundant frame for SILK->CELT */
407     if (redundancy && !celt_to_silk)
408     {
409         int N2, N4;
410         N2 = st->Fs/200;
411         N4 = st->Fs/400;
412
413         celt_encoder_ctl(st->celt_enc, CELT_RESET_STATE);
414         celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
415         celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(0));
416
417         /* FIXME: Do proper prefilling here */
418         celt_encode(st->celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, data+nb_compr_bytes, redundancy_bytes);
419
420         celt_encode(st->celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes);
421     }
422
423
424     if (frame_size>st->encoder_buffer)
425     {
426         for (i=0;i<st->encoder_buffer*st->channels;i++)
427                 st->delay_buffer[i] = pcm[(frame_size-st->encoder_buffer)*st->channels+i];
428     } else {
429         int tmp = st->encoder_buffer-frame_size;
430         for (i=0;i<tmp*st->channels;i++)
431                 st->delay_buffer[i] = st->delay_buffer[i+frame_size*st->channels];
432         for (i=0;i<frame_size*st->channels;i++)
433                 st->delay_buffer[tmp*st->channels+i] = pcm[i];
434     }
435
436         /* Signalling the mode in the first byte */
437         data--;
438         framerate = st->Fs/frame_size;
439         period = 0;
440         while (framerate < 400)
441         {
442             framerate <<= 1;
443             period++;
444         }
445     if (st->mode == MODE_SILK_ONLY)
446     {
447         data[0] = (silk_internal_bandwidth-BANDWIDTH_NARROWBAND)<<5;
448         data[0] |= (period-2)<<3;
449     } else if (st->mode == MODE_CELT_ONLY)
450     {
451         int tmp = st->bandwidth-BANDWIDTH_MEDIUMBAND;
452         if (tmp < 0)
453             tmp = 0;
454         data[0] = 0x80;
455         data[0] |= tmp << 5;
456         data[0] |= period<<3;
457     } else /* Hybrid */
458     {
459         data[0] = 0x60;
460         data[0] |= (st->bandwidth-BANDWIDTH_SUPERWIDEBAND)<<4;
461         data[0] |= (period-2)<<3;
462     }
463     data[0] |= (st->stream_channels==2)<<2;
464     /*printf ("%x\n", (int)data[0]);*/
465
466 #if OPUS_TEST_RANGE_CODER_STATE
467     st->rangeFinal = enc.rng;
468 #endif
469     if (to_celt)
470         st->prev_mode = MODE_CELT_ONLY;
471     else
472         st->prev_mode = st->mode;
473     return ret+1+redundancy_bytes;
474 }
475
476 void opus_encoder_ctl(OpusEncoder *st, int request, ...)
477 {
478     va_list ap;
479
480     va_start(ap, request);
481
482     switch (request)
483     {
484         case OPUS_SET_MODE_REQUEST:
485         {
486             int value = va_arg(ap, int);
487             st->user_mode = value;
488         }
489         break;
490         case OPUS_GET_MODE_REQUEST:
491         {
492             int *value = va_arg(ap, int*);
493             *value = st->user_mode;
494         }
495         break;
496         case OPUS_SET_BITRATE_REQUEST:
497         {
498             int value = va_arg(ap, int);
499             st->bitrate_bps = value;
500         }
501         break;
502         case OPUS_GET_BITRATE_REQUEST:
503         {
504             int *value = va_arg(ap, int*);
505             *value = st->bitrate_bps;
506         }
507         break;
508         case OPUS_SET_BANDWIDTH_REQUEST:
509         {
510             int value = va_arg(ap, int);
511             st->bandwidth = value;
512             if (st->bandwidth == BANDWIDTH_NARROWBAND) {
513                 st->silk_mode.maxInternalSampleRate = 8000;
514             } else if (st->bandwidth == BANDWIDTH_MEDIUMBAND) {
515                 st->silk_mode.maxInternalSampleRate = 12000;
516             } else {
517                 st->silk_mode.maxInternalSampleRate = 16000;
518             }
519         }
520         break;
521         case OPUS_GET_BANDWIDTH_REQUEST:
522         {
523             int *value = va_arg(ap, int*);
524             *value = st->bandwidth;
525         }
526         break;
527         case OPUS_SET_DTX_FLAG_REQUEST:
528         {
529             int value = va_arg(ap, int);
530             st->silk_mode.useDTX = value;
531         }
532         break;
533         case OPUS_GET_DTX_FLAG_REQUEST:
534         {
535             int *value = va_arg(ap, int*);
536             *value = st->silk_mode.useDTX;
537         }
538         break;
539         case OPUS_SET_COMPLEXITY_REQUEST:
540         {
541             int value = va_arg(ap, int);
542             st->silk_mode.complexity = value;
543             celt_encoder_ctl(st->celt_enc, CELT_SET_COMPLEXITY(value));
544         }
545         break;
546         case OPUS_GET_COMPLEXITY_REQUEST:
547         {
548             int *value = va_arg(ap, int*);
549             *value = st->silk_mode.complexity;
550         }
551         break;
552         case OPUS_SET_INBAND_FEC_FLAG_REQUEST:
553         {
554             int value = va_arg(ap, int);
555             st->silk_mode.useInBandFEC = value;
556         }
557         break;
558         case OPUS_GET_INBAND_FEC_FLAG_REQUEST:
559         {
560             int *value = va_arg(ap, int*);
561             *value = st->silk_mode.useInBandFEC;
562         }
563         break;
564         case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
565         {
566             int value = va_arg(ap, int);
567             st->silk_mode.packetLossPercentage = value;
568         }
569         break;
570         case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
571         {
572             int *value = va_arg(ap, int*);
573             *value = st->silk_mode.packetLossPercentage;
574         }
575         break;
576         case OPUS_SET_VBR_FLAG_REQUEST:
577         {
578             int value = va_arg(ap, int);
579             st->use_vbr = value;
580             st->silk_mode.useCBR = 1-value;
581         }
582         break;
583         case OPUS_GET_VBR_FLAG_REQUEST:
584         {
585             int *value = va_arg(ap, int*);
586             *value = st->use_vbr;
587         }
588         break;
589         case OPUS_SET_VOICE_RATIO_REQUEST:
590         {
591             int value = va_arg(ap, int);
592             st->voice_ratio = value;
593         }
594         break;
595         case OPUS_GET_VOICE_RATIO_REQUEST:
596         {
597             int *value = va_arg(ap, int*);
598             *value = st->voice_ratio;
599         }
600         break;
601         default:
602             fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);
603             break;
604     }
605
606     va_end(ap);
607 }
608
609 void opus_encoder_destroy(OpusEncoder *st)
610 {
611         free(st);
612 }
613
614 #if OPUS_TEST_RANGE_CODER_STATE
615 int opus_encoder_get_final_range(OpusEncoder *st)
616 {
617     return st->rangeFinal;
618 }
619 #endif