Simple mode selection logic
This commit is contained in:
parent
1b16fec484
commit
f9bc460e36
5 changed files with 142 additions and 10 deletions
27
src/opus.h
27
src/opus.h
|
@ -43,8 +43,30 @@ extern "C" {
|
|||
#define __check_int(x) (((void)((x) == (int)0)), (int)(x))
|
||||
#define __check_int_ptr(ptr) ((ptr) + ((ptr) - (int*)(ptr)))
|
||||
|
||||
/* Error codes */
|
||||
/** No error */
|
||||
#define OPUS_OK 0
|
||||
/** An (or more) invalid argument (e.g. out of range) */
|
||||
#define OPUS_BAD_ARG -1
|
||||
/** The mode struct passed is invalid */
|
||||
#define OPUS_INVALID_MODE -2
|
||||
/** An internal error was detected */
|
||||
#define OPUS_INTERNAL_ERROR -3
|
||||
/** The data passed (e.g. compressed data to decoder) is corrupted */
|
||||
#define OPUS_CORRUPTED_DATA -4
|
||||
/** Invalid/unsupported request number */
|
||||
#define OPUS_UNIMPLEMENTED -5
|
||||
/** An encoder or decoder structure is invalid or already freed */
|
||||
#define OPUS_INVALID_STATE -6
|
||||
/** Memory allocation has failed */
|
||||
#define OPUS_ALLOC_FAIL -7
|
||||
|
||||
#define OPUS_TEST_RANGE_CODER_STATE 1
|
||||
|
||||
#define OPUS_MODE_AUTO 2000
|
||||
#define OPUS_MODE_VOICE 2001
|
||||
#define OPUS_MODE_AUDIO 2002
|
||||
|
||||
#define MODE_SILK_ONLY 1000
|
||||
#define MODE_HYBRID 1001
|
||||
#define MODE_CELT_ONLY 1002
|
||||
|
@ -97,6 +119,11 @@ extern "C" {
|
|||
#define OPUS_GET_DTX_FLAG_REQUEST 17
|
||||
#define OPUS_GET_DTX_FLAG(x) OPUS_GET_DTX_FLAG_REQUEST, __check_int_ptr(x)
|
||||
|
||||
#define OPUS_SET_VOICE_RATIO_REQUEST 18
|
||||
#define OPUS_SET_VOICE_RATIO(x) OPUS_SET_VOICE_RATIO_REQUEST, __check_int(x)
|
||||
#define OPUS_GET_VOICE_RATIO_REQUEST 19
|
||||
#define OPUS_GET_VOICE_RATIO(x) OPUS_GET_VOICE_RATIO_REQUEST, __check_int_ptr(x)
|
||||
|
||||
typedef struct OpusEncoder OpusEncoder;
|
||||
typedef struct OpusDecoder OpusDecoder;
|
||||
|
||||
|
|
|
@ -142,6 +142,12 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
|
|||
mode = st->prev_mode;
|
||||
}
|
||||
|
||||
if (st->stream_channels > st->channels)
|
||||
return OPUS_CORRUPTED_DATA;
|
||||
|
||||
if (st->stream_channels == 2 && mode != MODE_CELT_ONLY)
|
||||
return OPUS_UNIMPLEMENTED;
|
||||
|
||||
if (data!=NULL && !st->prev_redundancy && mode != st->prev_mode && st->prev_mode > 0
|
||||
&& !(mode == MODE_SILK_ONLY && st->prev_mode == MODE_HYBRID)
|
||||
&& !(mode == MODE_HYBRID && st->prev_mode == MODE_SILK_ONLY))
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
OpusEncoder *opus_encoder_create(int Fs, int channels)
|
||||
{
|
||||
int err;
|
||||
char *raw_state;
|
||||
OpusEncoder *st;
|
||||
int ret, silkEncSizeBytes, celtEncSizeBytes;
|
||||
|
@ -74,12 +75,14 @@ OpusEncoder *opus_encoder_create(int Fs, int channels)
|
|||
|
||||
/* Create CELT encoder */
|
||||
/* Initialize CELT encoder */
|
||||
st->celt_enc = celt_encoder_init(st->celt_enc, Fs, channels, NULL);
|
||||
st->celt_enc = celt_encoder_init(st->celt_enc, Fs, channels, &err);
|
||||
|
||||
st->mode = MODE_HYBRID;
|
||||
st->bandwidth = BANDWIDTH_FULLBAND;
|
||||
st->use_vbr = 0;
|
||||
st->bitrate_bps = 32000;
|
||||
st->user_mode = OPUS_MODE_AUTO;
|
||||
st->voice_ratio = 90;
|
||||
|
||||
st->encoder_buffer = st->Fs/100;
|
||||
st->delay_compensation = st->Fs/400;
|
||||
|
@ -106,6 +109,88 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
|||
short pcm_buf[960*2];
|
||||
int nb_compr_bytes;
|
||||
int to_celt = 0;
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
|
||||
printf("%d %d %d\n", st->stream_channels, st->mode, st->bandwidth);
|
||||
|
||||
bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1;
|
||||
|
||||
|
@ -399,13 +484,13 @@ void opus_encoder_ctl(OpusEncoder *st, int request, ...)
|
|||
case OPUS_SET_MODE_REQUEST:
|
||||
{
|
||||
int value = va_arg(ap, int);
|
||||
st->mode = value;
|
||||
st->user_mode = value;
|
||||
}
|
||||
break;
|
||||
case OPUS_GET_MODE_REQUEST:
|
||||
{
|
||||
int *value = va_arg(ap, int*);
|
||||
*value = st->mode;
|
||||
*value = st->user_mode;
|
||||
}
|
||||
break;
|
||||
case OPUS_SET_BITRATE_REQUEST:
|
||||
|
@ -501,6 +586,18 @@ void opus_encoder_ctl(OpusEncoder *st, int request, ...)
|
|||
*value = st->use_vbr;
|
||||
}
|
||||
break;
|
||||
case OPUS_SET_VOICE_RATIO_REQUEST:
|
||||
{
|
||||
int value = va_arg(ap, int);
|
||||
st->voice_ratio = value;
|
||||
}
|
||||
break;
|
||||
case OPUS_GET_VOICE_RATIO_REQUEST:
|
||||
{
|
||||
int *value = va_arg(ap, int*);
|
||||
*value = st->voice_ratio;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);
|
||||
break;
|
||||
|
|
|
@ -43,8 +43,10 @@ struct OpusEncoder {
|
|||
int stream_channels;
|
||||
|
||||
int mode;
|
||||
int user_mode;
|
||||
int prev_mode;
|
||||
int bandwidth;
|
||||
int voice_ratio;
|
||||
/* Sampling rate (at the API level) */
|
||||
int Fs;
|
||||
int use_vbr;
|
||||
|
|
|
@ -44,7 +44,7 @@ void print_usage( char* argv[] )
|
|||
{
|
||||
fprintf(stderr, "Usage: %s <mode (0/1/2)> <sampling rate (Hz)> <channels> "
|
||||
"<bits per second> [options] <input> <output>\n\n", argv[0]);
|
||||
fprintf(stderr, "mode: 0 for SILK, 1 for hybrid, 2 for CELT:\n" );
|
||||
fprintf(stderr, "mode: 0 for audo, 1 for voice, 2 for audio:\n" );
|
||||
fprintf(stderr, "options:\n" );
|
||||
fprintf(stderr, "-cbr : enable constant bitrate; default: VBR\n" );
|
||||
fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
|
||||
|
@ -103,7 +103,7 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
mode = atoi(argv[1]) + MODE_SILK_ONLY;
|
||||
mode = atoi(argv[1]) + OPUS_MODE_AUTO;
|
||||
sampling_rate = atoi(argv[2]);
|
||||
channels = atoi(argv[3]);
|
||||
bitrate_bps = atoi(argv[4]);
|
||||
|
@ -200,7 +200,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if( mode < MODE_SILK_ONLY || mode > MODE_CELT_ONLY ) {
|
||||
if( mode < OPUS_MODE_AUTO || mode > OPUS_MODE_AUDIO) {
|
||||
fprintf (stderr, "mode must be: 0, 1 or 2\n");
|
||||
return 1;
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (mode==MODE_SILK_ONLY)
|
||||
/*if (mode==MODE_SILK_ONLY)
|
||||
{
|
||||
if (bandwidth == BANDWIDTH_SUPERWIDEBAND || bandwidth == BANDWIDTH_FULLBAND)
|
||||
{
|
||||
|
@ -256,7 +256,7 @@ int main(int argc, char *argv[])
|
|||
fprintf (stderr, "Transform mode does not support mediumband\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
enc = opus_encoder_create(sampling_rate, channels);
|
||||
dec = opus_decoder_create(sampling_rate, channels);
|
||||
|
@ -277,8 +277,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
skip = 5*sampling_rate/1000;
|
||||
/* When SILK resamples, add 18 samples delay */
|
||||
if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
|
||||
skip += 18;
|
||||
/*if (mode != MODE_SILK_ONLY || sampling_rate > 16000)
|
||||
skip += 18;*/
|
||||
|
||||
switch(bandwidth)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue