Removes auto mode and fixes a force_mono issue
This commit is contained in:
parent
be75f1d0fe
commit
479e18bcb7
5 changed files with 81 additions and 55 deletions
63
src/opus.h
63
src/opus.h
|
@ -65,9 +65,8 @@ extern "C" {
|
||||||
|
|
||||||
#define OPUS_BITRATE_AUTO -1
|
#define OPUS_BITRATE_AUTO -1
|
||||||
|
|
||||||
#define OPUS_MODE_AUTO 2000
|
#define OPUS_MODE_VOICE 2000
|
||||||
#define OPUS_MODE_VOICE 2001
|
#define OPUS_MODE_AUDIO 2001
|
||||||
#define OPUS_MODE_AUDIO 2002
|
|
||||||
|
|
||||||
#define MODE_SILK_ONLY 1000
|
#define MODE_SILK_ONLY 1000
|
||||||
#define MODE_HYBRID 1001
|
#define MODE_HYBRID 1001
|
||||||
|
@ -140,25 +139,65 @@ extern "C" {
|
||||||
typedef struct OpusEncoder OpusEncoder;
|
typedef struct OpusEncoder OpusEncoder;
|
||||||
typedef struct OpusDecoder OpusDecoder;
|
typedef struct OpusDecoder OpusDecoder;
|
||||||
|
|
||||||
OPUS_EXPORT OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels);
|
/*
|
||||||
|
* There are two coding modes:
|
||||||
|
* OPUS_MODE_VOICE gives best quality at a given bitrate for voice signals. It enhances the
|
||||||
|
* input signal by high-pass filtering and emphasizing formants and harmonics. Optionally
|
||||||
|
* it includes in-band forward error correction to protect against packet loss. Use this
|
||||||
|
* mode for typical VoIP applications. Because of the enhancement, even at high bitrates
|
||||||
|
* the output may sound different from the input.
|
||||||
|
* OPUS_MODE_AUDIO gives best quality at a given bitrate for most non-voice signals like music.
|
||||||
|
* Use this mode for music and mixed (music/voice) content, and applications requiring less
|
||||||
|
* than 15 ms of coding delay.
|
||||||
|
*/
|
||||||
|
|
||||||
OPUS_EXPORT OpusEncoder *opus_encoder_create(int Fs, int channels);
|
/* Returns initialized encoder state */
|
||||||
|
OPUS_EXPORT OpusEncoder *opus_encoder_create(
|
||||||
|
int Fs, /* Sampling rate of input signal (Hz) */
|
||||||
|
int channels, /* Number of channels (1/2) in input signal */
|
||||||
|
int mode /* Coding mode (OPUS_MODE_VOICE/OPUS_MODE_AUDIO) */
|
||||||
|
);
|
||||||
|
|
||||||
|
OPUS_EXPORT OpusEncoder *opus_encoder_init(
|
||||||
|
OpusEncoder *st, /* Encoder state */
|
||||||
|
int Fs, /* Sampling rate of input signal (Hz) */
|
||||||
|
int channels, /* Number of channels (1/2) in input signal */
|
||||||
|
int mode /* Coding mode (OPUS_MODE_VOICE/OPUS_MODE_AUDIO) */
|
||||||
|
);
|
||||||
|
|
||||||
/* returns length of data payload (in bytes) */
|
/* returns length of data payload (in bytes) */
|
||||||
OPUS_EXPORT int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
OPUS_EXPORT int opus_encode(
|
||||||
unsigned char *data, int max_data_bytes);
|
OpusEncoder *st, /* Encoder state */
|
||||||
|
const short *pcm, /* Input signal (interleaved if 2 channels). length is frame_size*channels */
|
||||||
|
int frame_size, /* Number of samples per frame of input signal */
|
||||||
|
unsigned char *data, /* Output payload (no more than max_data_bytes long) */
|
||||||
|
int max_data_bytes /* Allocated memory for payload; don't use for controlling bitrate */
|
||||||
|
);
|
||||||
|
|
||||||
OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
|
OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
|
||||||
|
|
||||||
OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...);
|
OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...);
|
||||||
|
|
||||||
OPUS_EXPORT OpusDecoder *opus_decoder_init(OpusDecoder *st, int Fs, int channels);
|
OPUS_EXPORT OpusDecoder *opus_decoder_create(
|
||||||
|
int Fs, /* Sampling rate of output signal (Hz) */
|
||||||
|
int channels /* Number of channels (1/2) in output signal */
|
||||||
|
);
|
||||||
|
|
||||||
OPUS_EXPORT OpusDecoder *opus_decoder_create(int Fs, int channels);
|
OPUS_EXPORT OpusDecoder *opus_decoder_init(OpusDecoder *st,
|
||||||
|
int Fs, /* Sampling rate of output signal (Hz) */
|
||||||
|
int channels /* Number of channels (1/2) in output signal */
|
||||||
|
);
|
||||||
|
|
||||||
/* returns (CELT) error code */
|
/* returns (CELT) error code */
|
||||||
OPUS_EXPORT int opus_decode(OpusDecoder *st, const unsigned char *data, int len,
|
OPUS_EXPORT int opus_decode(
|
||||||
short *pcm, int frame_size, int decode_fec);
|
OpusDecoder *st, /* Decoder state */
|
||||||
|
const unsigned char *data, /* Input payload. Use a NULL pointer to indicate packet loss */
|
||||||
|
int len, /* Number of bytes in payload */
|
||||||
|
short *pcm, /* Output signal (interleaved if 2 channels). length is frame_size*channels */
|
||||||
|
int frame_size, /* Number of samples per frame of input signal */
|
||||||
|
int decode_fec /* Flag (0/1) to request that any in-band forward error correction data be */
|
||||||
|
/* decoded. If no such data is available the frame is decoded as if it were lost. */
|
||||||
|
);
|
||||||
|
|
||||||
OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...);
|
OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...);
|
||||||
|
|
||||||
|
@ -170,7 +209,7 @@ OPUS_EXPORT int opus_packet_get_nb_channels(const unsigned char *data);
|
||||||
OPUS_EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len);
|
OPUS_EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len);
|
||||||
OPUS_EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len);
|
OPUS_EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len);
|
||||||
|
|
||||||
|
/* For testing purposes: the encoder and decoder state should always be identical after coding a payload */
|
||||||
#if OPUS_TEST_RANGE_CODER_STATE
|
#if OPUS_TEST_RANGE_CODER_STATE
|
||||||
OPUS_EXPORT int opus_encoder_get_final_range(OpusEncoder *st);
|
OPUS_EXPORT int opus_encoder_get_final_range(OpusEncoder *st);
|
||||||
OPUS_EXPORT int opus_decoder_get_final_range(OpusDecoder *st);
|
OPUS_EXPORT int opus_decoder_get_final_range(OpusDecoder *st);
|
||||||
|
|
|
@ -103,7 +103,7 @@ failure:
|
||||||
|
|
||||||
OpusDecoder *opus_decoder_create(int Fs, int channels)
|
OpusDecoder *opus_decoder_create(int Fs, int channels)
|
||||||
{
|
{
|
||||||
char *raw_state = malloc(opus_decoder_get_size(channels));
|
char *raw_state = (char*)malloc(opus_decoder_get_size(channels));
|
||||||
if (raw_state == NULL)
|
if (raw_state == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return opus_decoder_init((OpusDecoder*)raw_state, Fs, channels);
|
return opus_decoder_init((OpusDecoder*)raw_state, Fs, channels);
|
||||||
|
|
|
@ -75,7 +75,7 @@ int opus_encoder_get_size(int channels)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels)
|
OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int mode)
|
||||||
{
|
{
|
||||||
void *silk_enc;
|
void *silk_enc;
|
||||||
CELTEncoder *celt_enc;
|
CELTEncoder *celt_enc;
|
||||||
|
@ -115,6 +115,7 @@ OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels)
|
||||||
st->silk_mode.useInBandFEC = 0;
|
st->silk_mode.useInBandFEC = 0;
|
||||||
st->silk_mode.useDTX = 0;
|
st->silk_mode.useDTX = 0;
|
||||||
st->silk_mode.useCBR = 0;
|
st->silk_mode.useCBR = 0;
|
||||||
|
st->silk_mode.HP_cutoff_Hz = 0;
|
||||||
|
|
||||||
st->hybrid_stereo_width_Q14 = 1 << 14;
|
st->hybrid_stereo_width_Q14 = 1 << 14;
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels)
|
||||||
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 = OPUS_MODE_AUTO;
|
st->user_mode = mode;
|
||||||
st->user_bandwidth = BANDWIDTH_AUTO;
|
st->user_bandwidth = BANDWIDTH_AUTO;
|
||||||
st->voice_ratio = 90;
|
st->voice_ratio = 90;
|
||||||
st->first = 1;
|
st->first = 1;
|
||||||
|
@ -145,12 +146,12 @@ failure:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpusEncoder *opus_encoder_create(int Fs, int channels)
|
OpusEncoder *opus_encoder_create(int Fs, int channels, int mode)
|
||||||
{
|
{
|
||||||
char *raw_state = (char *)malloc(opus_encoder_get_size(channels));
|
char *raw_state = (char *)malloc(opus_encoder_get_size(channels));
|
||||||
if (raw_state == NULL)
|
if (raw_state == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return opus_encoder_init((OpusEncoder*)raw_state, Fs, channels);
|
return opus_encoder_init((OpusEncoder*)raw_state, Fs, channels, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
||||||
|
@ -160,7 +161,7 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
||||||
CELTEncoder *celt_enc;
|
CELTEncoder *celt_enc;
|
||||||
int i;
|
int i;
|
||||||
int ret=0;
|
int ret=0;
|
||||||
SKP_int32 nBytes;
|
int nBytes;
|
||||||
ec_enc enc;
|
ec_enc enc;
|
||||||
int framerate, period;
|
int framerate, period;
|
||||||
int silk_internal_bandwidth=-1;
|
int silk_internal_bandwidth=-1;
|
||||||
|
@ -187,8 +188,9 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
||||||
|
|
||||||
/* Rate-dependent mono-stereo decision */
|
/* Rate-dependent mono-stereo decision */
|
||||||
if (st->force_mono)
|
if (st->force_mono)
|
||||||
|
{
|
||||||
st->stream_channels = 1;
|
st->stream_channels = 1;
|
||||||
if (st->mode == MODE_CELT_ONLY && st->channels == 2)
|
} else if (st->mode == MODE_CELT_ONLY && st->channels == 2)
|
||||||
{
|
{
|
||||||
celt_int32 decision_rate;
|
celt_int32 decision_rate;
|
||||||
decision_rate = st->bitrate_bps + st->voice_ratio*st->voice_ratio;
|
decision_rate = st->bitrate_bps + st->voice_ratio*st->voice_ratio;
|
||||||
|
@ -213,21 +215,7 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
||||||
mono_rate -= 60*(st->Fs/frame_size - 50);
|
mono_rate -= 60*(st->Fs/frame_size - 50);
|
||||||
|
|
||||||
/* Mode selection */
|
/* Mode selection */
|
||||||
if (st->user_mode==OPUS_MODE_AUTO)
|
if (st->user_mode==OPUS_MODE_VOICE)
|
||||||
{
|
|
||||||
celt_int32 decision_rate;
|
|
||||||
/* SILK/CELT threshold is higher for voice than for music */
|
|
||||||
decision_rate = mono_rate - 3*st->voice_ratio*st->voice_ratio;
|
|
||||||
/* Hysteresis */
|
|
||||||
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;
|
st->mode = MODE_SILK_ONLY;
|
||||||
} else {/* OPUS_AUDIO_MODE */
|
} else {/* OPUS_AUDIO_MODE */
|
||||||
|
@ -525,7 +513,6 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
|
||||||
|
|
||||||
if (st->mode != MODE_SILK_ONLY)
|
if (st->mode != MODE_SILK_ONLY)
|
||||||
{
|
{
|
||||||
/* Encode high band with CELT */
|
|
||||||
ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
|
ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,10 +42,10 @@ struct OpusEncoder {
|
||||||
int hybrid_stereo_width_Q14;
|
int hybrid_stereo_width_Q14;
|
||||||
int channels;
|
int channels;
|
||||||
int stream_channels;
|
int stream_channels;
|
||||||
|
int force_mono;
|
||||||
|
|
||||||
int mode;
|
int mode;
|
||||||
int user_mode;
|
int user_mode;
|
||||||
int force_mono;
|
|
||||||
int prev_mode;
|
int prev_mode;
|
||||||
int bandwidth;
|
int bandwidth;
|
||||||
int user_bandwidth;
|
int user_bandwidth;
|
||||||
|
|
|
@ -42,11 +42,12 @@
|
||||||
|
|
||||||
void print_usage( char* argv[] )
|
void print_usage( char* argv[] )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s <mode (0/1/2)> <sampling rate (Hz)> <channels> "
|
fprintf(stderr, "Usage: %s <mode (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 auto, 1 for voice, 2 for audio:\n" );
|
fprintf(stderr, "mode: 0 for voice, 1 for audio:\n" );
|
||||||
fprintf(stderr, "options:\n" );
|
fprintf(stderr, "options:\n" );
|
||||||
fprintf(stderr, "-cbr : enable constant bitrate; default: VBR\n" );
|
fprintf(stderr, "-cbr : enable constant bitrate; default: variable bitrate\n" );
|
||||||
|
fprintf(stderr, "-cvbr : enable constraint variable bitrate; default: unconstraint\n" );
|
||||||
fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
|
fprintf(stderr, "-bandwidth <NB|MB|WB|SWB|FB> : audio bandwidth (from narrowband to fullband); default: sampling rate\n" );
|
||||||
fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
|
fprintf(stderr, "-framesize <2.5|5|10|20|40|60> : frame size in ms; default: 20 \n" );
|
||||||
fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
|
fprintf(stderr, "-max_payload <bytes> : maximum payload size in bytes, default: 1024\n" );
|
||||||
|
@ -106,7 +107,7 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mode = atoi(argv[1]) + OPUS_MODE_AUTO;
|
mode = atoi(argv[1]) + OPUS_MODE_VOICE;
|
||||||
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]);
|
||||||
|
@ -199,8 +200,8 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( mode < OPUS_MODE_AUTO || mode > OPUS_MODE_AUDIO) {
|
if( mode < OPUS_MODE_VOICE || mode > OPUS_MODE_AUDIO) {
|
||||||
fprintf (stderr, "mode must be: 0, 1 or 2\n");
|
fprintf (stderr, "mode must be: 0 or 1\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +233,7 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enc = opus_encoder_create(sampling_rate, channels);
|
enc = opus_encoder_create(sampling_rate, channels, mode);
|
||||||
dec = opus_decoder_create(sampling_rate, channels);
|
dec = opus_decoder_create(sampling_rate, channels);
|
||||||
|
|
||||||
if (enc==NULL)
|
if (enc==NULL)
|
||||||
|
@ -246,7 +247,6 @@ int main(int argc, char *argv[])
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
|
|
||||||
opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
|
opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
|
||||||
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
|
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
|
||||||
opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
|
opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue