splitting encoder config in terms of application and signal type

This commit is contained in:
Jean-Marc Valin 2011-05-26 15:06:30 -04:00
parent 541df0a97e
commit 00cb6f7ab4
4 changed files with 69 additions and 19 deletions

View file

@ -65,8 +65,12 @@ extern "C" {
#define OPUS_BITRATE_AUTO -1 #define OPUS_BITRATE_AUTO -1
#define OPUS_MODE_VOICE 2000 #define OPUS_APPLICATION_VOIP 2000
#define OPUS_MODE_AUDIO 2001 #define OPUS_APPLICATION_AUDIO 2001
#define OPUS_SIGNAL_AUTO 3000
#define OPUS_SIGNAL_VOICE 3001
#define OPUS_SIGNAL_MUSIC 3002
#define MODE_SILK_ONLY 1000 #define MODE_SILK_ONLY 1000
#define MODE_HYBRID 1001 #define MODE_HYBRID 1001
@ -136,6 +140,11 @@ extern "C" {
#define OPUS_GET_FORCE_MONO_REQUEST 23 #define OPUS_GET_FORCE_MONO_REQUEST 23
#define OPUS_GET_FORCE_MONO(x) OPUS_GET_FORCE_MONO_REQUEST, __check_int_ptr(x) #define OPUS_GET_FORCE_MONO(x) OPUS_GET_FORCE_MONO_REQUEST, __check_int_ptr(x)
#define OPUS_SET_SIGNAL_REQUEST 24
#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __check_int(x)
#define OPUS_GET_SIGNAL_REQUEST 25
#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __check_int_ptr(x)
typedef struct OpusEncoder OpusEncoder; typedef struct OpusEncoder OpusEncoder;
typedef struct OpusDecoder OpusDecoder; typedef struct OpusDecoder OpusDecoder;
@ -155,14 +164,14 @@ typedef struct OpusDecoder OpusDecoder;
OPUS_EXPORT OpusEncoder *opus_encoder_create( OPUS_EXPORT OpusEncoder *opus_encoder_create(
int Fs, /* Sampling rate of input signal (Hz) */ int Fs, /* Sampling rate of input signal (Hz) */
int channels, /* Number of channels (1/2) in input signal */ int channels, /* Number of channels (1/2) in input signal */
int mode /* Coding mode (OPUS_MODE_VOICE/OPUS_MODE_AUDIO) */ int application /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
); );
OPUS_EXPORT OpusEncoder *opus_encoder_init( OPUS_EXPORT OpusEncoder *opus_encoder_init(
OpusEncoder *st, /* Encoder state */ OpusEncoder *st, /* Encoder state */
int Fs, /* Sampling rate of input signal (Hz) */ int Fs, /* Sampling rate of input signal (Hz) */
int channels, /* Number of channels (1/2) in input signal */ int channels, /* Number of channels (1/2) in input signal */
int mode /* Coding mode (OPUS_MODE_VOICE/OPUS_MODE_AUDIO) */ int application /* Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO) */
); );
/* returns length of data payload (in bytes) */ /* returns length of data payload (in bytes) */

View file

@ -75,7 +75,7 @@ int opus_encoder_get_size(int channels)
} }
OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int mode) OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int application)
{ {
void *silk_enc; void *silk_enc;
CELTEncoder *celt_enc; CELTEncoder *celt_enc;
@ -131,7 +131,8 @@ OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int mode)
st->use_vbr = 0; st->use_vbr = 0;
st->user_bitrate_bps = OPUS_BITRATE_AUTO; st->user_bitrate_bps = OPUS_BITRATE_AUTO;
st->bitrate_bps = 3000+Fs*channels; st->bitrate_bps = 3000+Fs*channels;
st->user_mode = mode; st->user_mode = application;
st->signal_type = OPUS_SIGNAL_AUTO;
st->user_bandwidth = OPUS_BANDWIDTH_AUTO; st->user_bandwidth = OPUS_BANDWIDTH_AUTO;
st->voice_ratio = 90; st->voice_ratio = 90;
st->first = 1; st->first = 1;
@ -209,19 +210,46 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
/* Equivalent bit-rate for mono */ /* Equivalent bit-rate for mono */
mono_rate = st->bitrate_bps; mono_rate = st->bitrate_bps;
if (st->stream_channels==2) if (st->stream_channels==2)
mono_rate = (mono_rate+10000)/2; mono_rate = 2*mono_rate/3;
/* Compensate for smaller frame sizes assuming an equivalent overhead /* Compensate for smaller frame sizes assuming an equivalent overhead
of 60 bits/frame */ of 60 bits/frame */
mono_rate -= 60*(st->Fs/frame_size - 50); mono_rate -= 60*(st->Fs/frame_size - 50);
/* Mode selection */ /* Mode selection depending on application and signal type */
if (st->user_mode==OPUS_MODE_VOICE) if (st->user_mode==OPUS_APPLICATION_VOIP)
{ {
st->mode = MODE_SILK_ONLY; celt_int32 threshold = 20000;
} else {/* OPUS_AUDIO_MODE */ /* Hysteresis */
st->mode = MODE_CELT_ONLY; if (st->prev_mode == MODE_CELT_ONLY)
} threshold -= 4000;
else if (st->prev_mode>0)
threshold += 4000;
/* OPUS_APPLICATION_VOIP defaults to MODE_SILK_ONLY */
if (st->signal_type == OPUS_SIGNAL_MUSIC && mono_rate > threshold)
st->mode = MODE_CELT_ONLY;
else
st->mode = MODE_SILK_ONLY;
} else {/* OPUS_APPLICATION_AUDIO */
celt_int32 threshold;
/* SILK/CELT threshold is higher for voice than for music */
threshold = 36000;
if (st->signal_type == OPUS_SIGNAL_MUSIC)
threshold -= 20000;
else if (st->signal_type == OPUS_SIGNAL_VOICE)
threshold += 8000;
/* Hysteresis */
if (st->prev_mode == MODE_CELT_ONLY)
threshold -= 4000;
else if (st->prev_mode>0)
threshold += 4000;
if (mono_rate>threshold)
st->mode = MODE_CELT_ONLY;
else
st->mode = MODE_SILK_ONLY;
}
/* Automatic (rate-dependent) bandwidth selection */ /* Automatic (rate-dependent) bandwidth selection */
if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch) if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch)
{ {
@ -753,6 +781,18 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
*value = st->vbr_constraint; *value = st->vbr_constraint;
} }
break; break;
case OPUS_SET_SIGNAL_REQUEST:
{
int value = va_arg(ap, int);
st->signal_type = value;
}
break;
case OPUS_GET_SIGNAL_REQUEST:
{
int *value = va_arg(ap, int*);
*value = st->signal_type;
}
break;
default: default:
fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request); fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);
break; break;

View file

@ -47,6 +47,7 @@ struct OpusEncoder {
int mode; int mode;
int user_mode; int user_mode;
int prev_mode; int prev_mode;
int signal_type;
int bandwidth; int bandwidth;
int user_bandwidth; int user_bandwidth;
int voice_ratio; int voice_ratio;

View file

@ -42,9 +42,9 @@
void print_usage( char* argv[] ) void print_usage( char* argv[] )
{ {
fprintf(stderr, "Usage: %s <mode (0/1)> <sampling rate (Hz)> <channels (1/2)> " fprintf(stderr, "Usage: %s <application (0/1)> <sampling rate (Hz)> <channels (1/2)> "
"<bits per second> [options] <input> <output>\n\n", argv[0]); "<bits per second> [options] <input> <output>\n\n", argv[0]);
fprintf(stderr, "mode: 0 for voice, 1 for audio:\n" ); fprintf(stderr, "mode: 0 for VoIP, 1 for audio:\n" );
fprintf(stderr, "options:\n" ); fprintf(stderr, "options:\n" );
fprintf(stderr, "-cbr : enable constant bitrate; default: variable bitrate\n" ); fprintf(stderr, "-cbr : enable constant bitrate; default: variable bitrate\n" );
fprintf(stderr, "-cvbr : enable constraint variable bitrate; default: unconstraint\n" ); fprintf(stderr, "-cvbr : enable constraint variable bitrate; default: unconstraint\n" );
@ -92,7 +92,7 @@ int main(int argc, char *argv[])
int stop=0; int stop=0;
int tot_read=0, tot_written=0; int tot_read=0, tot_written=0;
short *in, *out; short *in, *out;
int mode; int application;
double bits=0.0, bits_act=0.0, bits2=0.0, nrg; double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
int bandwidth=-1; int bandwidth=-1;
const char *bandwidth_string; const char *bandwidth_string;
@ -107,7 +107,7 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
mode = atoi(argv[1]) + OPUS_MODE_VOICE; application = atoi(argv[1]) + OPUS_APPLICATION_VOIP;
sampling_rate = atoi(argv[2]); sampling_rate = atoi(argv[2]);
channels = atoi(argv[3]); channels = atoi(argv[3]);
bitrate_bps = atoi(argv[4]); bitrate_bps = atoi(argv[4]);
@ -200,7 +200,7 @@ int main(int argc, char *argv[])
} }
} }
if( mode < OPUS_MODE_VOICE || mode > OPUS_MODE_AUDIO) { if( application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO) {
fprintf (stderr, "mode must be: 0 or 1\n"); fprintf (stderr, "mode must be: 0 or 1\n");
return 1; return 1;
} }
@ -233,7 +233,7 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
enc = opus_encoder_create(sampling_rate, channels, mode); enc = opus_encoder_create(sampling_rate, channels, application);
dec = opus_decoder_create(sampling_rate, channels); dec = opus_decoder_create(sampling_rate, channels);
if (enc==NULL) if (enc==NULL)