diff --git a/src/opus.h b/src/opus.h index 6bbd65825258fa140b2f3188fd07cf5a0ad34583..2d2fdffb3c88057b4f16afe60a0bd7fbbcf8615f 100644 --- a/src/opus.h +++ b/src/opus.h @@ -148,16 +148,18 @@ extern "C" { typedef struct OpusEncoder OpusEncoder; typedef struct OpusDecoder OpusDecoder; -/* - * There are two coding modes: - * OPUS_APPLICATION_VOIP 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_APPLICATION_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, broadcast, and applications requiring less - * than 15 ms of coding delay. +/* + * There are two coding modes: + * OPUS_APPLICATION_VOIP 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_APPLICATION_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, broadcast, and applications requiring less + * than 15 ms of coding delay. */ /* Returns initialized encoder state */ @@ -177,7 +179,7 @@ OPUS_EXPORT OpusEncoder *opus_encoder_init( /* Returns length of the data payload (in bytes) */ OPUS_EXPORT int opus_encode( OpusEncoder *st, /* Encoder state */ - const opus_int16 *pcm, /* Input signal (interleaved if 2 channels). length is frame_size*channels */ + const opus_int16 *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 */ @@ -192,7 +194,7 @@ OPUS_EXPORT OpusDecoder *opus_decoder_create( int channels /* Number of channels (1/2) in output signal */ ); -OPUS_EXPORT OpusDecoder *opus_decoder_init(OpusDecoder *st, +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 */ ); @@ -202,7 +204,7 @@ OPUS_EXPORT int opus_decode( 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 */ - opus_int16 *pcm, /* Output signal (interleaved if 2 channels). length is frame_size*channels */ + opus_int16 *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. */ @@ -222,7 +224,8 @@ OPUS_EXPORT const char *opus_strerror(int error); OPUS_EXPORT const char *opus_get_version_string(void); -/* For testing purposes: the encoder and decoder state should always be identical after coding a payload */ +/* For testing purposes: the encoder and decoder state should + always be identical after coding a payload */ OPUS_EXPORT int opus_encoder_get_final_range(OpusEncoder *st); OPUS_EXPORT int opus_decoder_get_final_range(OpusDecoder *st); diff --git a/src/opus_decoder.c b/src/opus_decoder.c index 305589c8b530b12b14bf062d0e04acde35ba49e4..58c51cfff759e65b8efffb857d6d9af56dc0cb5a 100644 --- a/src/opus_decoder.c +++ b/src/opus_decoder.c @@ -248,7 +248,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, do { /* Call SILK decoder */ int first_frame = decoded_samples == 0; - silk_ret = silk_Decode( silk_dec, &DecControl, + silk_ret = silk_Decode( silk_dec, &DecControl, lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size ); if( silk_ret ) { if (lost_flag) { diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 432fe3398d030445a2171439e7549eab3b8fc81f..9f831482548b58f39dc9683406d0dc624c6d8603 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -59,28 +59,27 @@ static const int audio_bandwidth_thresholds[10] = { on really weird architectures) */ static inline int align(int i) { - return (i+3)&-4; + return (i+3)&-4; } int opus_encoder_get_size(int channels) { - int silkEncSizeBytes, celtEncSizeBytes; - int ret; - ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); - if(ret) - return 0; - silkEncSizeBytes = align(silkEncSizeBytes); + int silkEncSizeBytes, celtEncSizeBytes; + int ret; + ret = silk_Get_Encoder_Size( &silkEncSizeBytes ); + if(ret) + return 0; + silkEncSizeBytes = align(silkEncSizeBytes); celtEncSizeBytes = celt_encoder_get_size(channels); return align(sizeof(OpusEncoder))+silkEncSizeBytes+celtEncSizeBytes; - } OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int application) { - void *silk_enc; - CELTEncoder *celt_enc; + void *silk_enc; + CELTEncoder *celt_enc; int err; - int ret, silkEncSizeBytes; + int ret, silkEncSizeBytes; if (channels > 2 || channels<1) return NULL; @@ -127,28 +126,29 @@ OpusEncoder *opus_encoder_init(OpusEncoder* st, int Fs, int channels, int applic st->hybrid_stereo_width_Q14 = 1 << 14; /* Create CELT encoder */ - /* Initialize CELT encoder */ - celt_encoder_init(celt_enc, Fs, channels, &err); - if (err != CELT_OK) + /* Initialize CELT encoder */ + celt_encoder_init(celt_enc, Fs, channels, &err); + if (err != CELT_OK) goto failure; celt_encoder_ctl(celt_enc, CELT_SET_SIGNALLING(0)); - st->mode = MODE_HYBRID; - st->bandwidth = OPUS_BANDWIDTH_FULLBAND; - st->use_vbr = 0; + st->mode = MODE_HYBRID; + st->bandwidth = OPUS_BANDWIDTH_FULLBAND; + st->use_vbr = 0; st->user_bitrate_bps = OPUS_BITRATE_AUTO; - st->bitrate_bps = 3000+Fs*channels; - st->user_mode = application; - st->signal_type = OPUS_SIGNAL_AUTO; - st->user_bandwidth = OPUS_BANDWIDTH_AUTO; - st->voice_ratio = 90; - st->first = 1; - - st->encoder_buffer = st->Fs/100; - st->delay_compensation = st->Fs/400; - if (st->Fs > 16000) - st->delay_compensation += 10; - return st; + st->bitrate_bps = 3000+Fs*channels; + st->user_mode = application; + st->signal_type = OPUS_SIGNAL_AUTO; + st->user_bandwidth = OPUS_BANDWIDTH_AUTO; + st->voice_ratio = 90; + st->first = 1; + + st->encoder_buffer = st->Fs/100; + st->delay_compensation = st->Fs/400; + if (st->Fs > 16000) + st->delay_compensation += 10; + return st; + failure: free(st); return NULL; @@ -165,13 +165,13 @@ OpusEncoder *opus_encoder_create(int Fs, int channels, int mode) int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, unsigned char *data, int max_data_bytes) { - void *silk_enc; - CELTEncoder *celt_enc; + void *silk_enc; + CELTEncoder *celt_enc; int i; - int ret=0; - int nBytes; - ec_enc enc; - int framerate, period; + int ret=0; + int nBytes; + ec_enc enc; + int framerate, period; int silk_internal_bandwidth=-1; int bytes_target; int prefill=0; @@ -179,7 +179,7 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, int redundancy = 0; int redundancy_bytes = 0; int celt_to_silk = 0; - /* TODO: This is 60 only so we can handle 60ms speech/audio switching + /* TODO: This is 60 only so we can handle 60ms speech/audio switching it shouldn't be too hard to reduce to 20 ms if needed */ opus_int16 pcm_buf[60*48*2]; int nb_compr_bytes; @@ -263,44 +263,44 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, /* Automatic (rate-dependent) bandwidth selection */ if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch) { - const int *bandwidth_thresholds; - int bandwidth = OPUS_BANDWIDTH_FULLBAND; - - bandwidth_thresholds = st->mode == MODE_CELT_ONLY ? audio_bandwidth_thresholds : voice_bandwidth_thresholds; - do { - int threshold, hysteresis; - threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)]; - hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1]; - if (!st->first) - { - if (st->bandwidth >= bandwidth) - threshold -= hysteresis; - else - threshold += hysteresis; - } - if (mono_rate >= threshold) - break; - } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND); - st->bandwidth = bandwidth; - /* Prevents any transition to SWB/FB until the SILK layer has fully - switched to WB mode and turned the variable LP filter off */ - if (st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) - st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + const int *bandwidth_thresholds; + int bandwidth = OPUS_BANDWIDTH_FULLBAND; + + bandwidth_thresholds = st->mode == MODE_CELT_ONLY ? audio_bandwidth_thresholds : voice_bandwidth_thresholds; + do { + int threshold, hysteresis; + threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)]; + hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1]; + if (!st->first) + { + if (st->bandwidth >= bandwidth) + threshold -= hysteresis; + else + threshold += hysteresis; + } + if (mono_rate >= threshold) + break; + } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND); + st->bandwidth = bandwidth; + /* Prevents any transition to SWB/FB until the SILK layer has fully + switched to WB mode and turned the variable LP filter off */ + if (st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; } /* Prevents Opus from wasting bits on frequencies that are above the Nyquist rate of the input signal */ if (st->Fs <= 24000 && st->bandwidth > OPUS_BANDWIDTH_SUPERWIDEBAND) - st->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; + st->bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND; if (st->Fs <= 16000 && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND) - st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; + st->bandwidth = OPUS_BANDWIDTH_WIDEBAND; if (st->Fs <= 12000 && st->bandwidth > OPUS_BANDWIDTH_MEDIUMBAND) - st->bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; + st->bandwidth = OPUS_BANDWIDTH_MEDIUMBAND; if (st->Fs <= 8000 && st->bandwidth > OPUS_BANDWIDTH_NARROWBAND) - st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; + st->bandwidth = OPUS_BANDWIDTH_NARROWBAND; if (st->user_bandwidth != OPUS_BANDWIDTH_AUTO) - st->bandwidth = st->user_bandwidth; + st->bandwidth = st->user_bandwidth; /* Preventing nonsensical configurations, i.e. modes that don't exist */ @@ -321,37 +321,37 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, if (st->mode == MODE_HYBRID && st->bandwidth <= OPUS_BANDWIDTH_WIDEBAND) st->mode = MODE_SILK_ONLY; - bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1; + bytes_target = st->bitrate_bps * frame_size / (st->Fs * 8) - 1; - data += 1; - if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) - { - silk_EncControlStruct dummy; - silk_InitEncoder( silk_enc, &dummy); - prefill=1; - } - if (st->prev_mode > 0 && - ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) || - (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY))) - { - redundancy = 1; - celt_to_silk = (st->mode != MODE_CELT_ONLY); - if (!celt_to_silk) - { - /* Switch to SILK/hybrid if frame size is 10 ms or more*/ - if (frame_size >= st->Fs/100) - { - st->mode = st->prev_mode; - to_celt = 1; - } else { - redundancy=0; - } - } + data += 1; + if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) + { + silk_EncControlStruct dummy; + silk_InitEncoder( silk_enc, &dummy); + prefill=1; + } + if (st->prev_mode > 0 && + ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) || + (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY))) + { + redundancy = 1; + celt_to_silk = (st->mode != MODE_CELT_ONLY); + if (!celt_to_silk) + { + /* Switch to SILK/hybrid if frame size is 10 ms or more*/ + if (frame_size >= st->Fs/100) + { + st->mode = st->prev_mode; + to_celt = 1; + } else { + redundancy=0; + } } + } - ec_enc_init(&enc, data, max_data_bytes-1); + ec_enc_init(&enc, data, max_data_bytes-1); - /* SILK processing */ + /* SILK processing */ if (st->mode != MODE_CELT_ONLY) { st->silk_mode.bitRate = st->bitrate_bps - 8*st->Fs/frame_size; @@ -385,9 +385,9 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, st->silk_mode.nChannelsAPI = st->channels; st->silk_mode.nChannelsInternal = st->stream_channels; if (st->bandwidth == OPUS_BANDWIDTH_NARROWBAND) { - st->silk_mode.desiredInternalSampleRate = 8000; + st->silk_mode.desiredInternalSampleRate = 8000; } else if (st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) { - st->silk_mode.desiredInternalSampleRate = 12000; + st->silk_mode.desiredInternalSampleRate = 12000; } else { SKP_assert( st->mode == MODE_HYBRID || st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ); st->silk_mode.desiredInternalSampleRate = 16000; @@ -405,7 +405,7 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, if (prefill) { int zero=0; - silk_Encode( silk_enc, &st->silk_mode, st->delay_buffer, st->encoder_buffer, NULL, &zero, 1 ); + silk_Encode( silk_enc, &st->silk_mode, st->delay_buffer, st->encoder_buffer, NULL, &zero, 1 ); } ret = silk_Encode( silk_enc, &st->silk_mode, pcm, frame_size, &enc, &nBytes, 0 ); @@ -430,42 +430,42 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, } /* CELT processing */ - { - int endband=21; - - switch(st->bandwidth) - { - case OPUS_BANDWIDTH_NARROWBAND: - endband = 13; - break; - case OPUS_BANDWIDTH_MEDIUMBAND: + { + int endband=21; + + switch(st->bandwidth) + { + case OPUS_BANDWIDTH_NARROWBAND: + endband = 13; + break; + case OPUS_BANDWIDTH_MEDIUMBAND: case OPUS_BANDWIDTH_WIDEBAND: - endband = 17; - break; - case OPUS_BANDWIDTH_SUPERWIDEBAND: - endband = 19; - break; - case OPUS_BANDWIDTH_FULLBAND: - endband = 21; - break; - } - celt_encoder_ctl(celt_enc, CELT_SET_END_BAND(endband)); - celt_encoder_ctl(celt_enc, CELT_SET_CHANNELS(st->stream_channels)); - } - if (st->mode != MODE_SILK_ONLY) - { + endband = 17; + break; + case OPUS_BANDWIDTH_SUPERWIDEBAND: + endband = 19; + break; + case OPUS_BANDWIDTH_FULLBAND: + endband = 21; + break; + } + celt_encoder_ctl(celt_enc, CELT_SET_END_BAND(endband)); + celt_encoder_ctl(celt_enc, CELT_SET_CHANNELS(st->stream_channels)); + } + if (st->mode != MODE_SILK_ONLY) + { celt_encoder_ctl(celt_enc, CELT_SET_VBR(0)); celt_encoder_ctl(celt_enc, CELT_SET_BITRATE(510000)); if (st->prev_mode == MODE_SILK_ONLY) { - unsigned char dummy[10]; - celt_encoder_ctl(celt_enc, CELT_RESET_STATE); - celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); - celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); - /* TODO: This wastes CPU a bit compared to just prefilling the buffer */ - celt_encode(celt_enc, &st->delay_buffer[(st->encoder_buffer-st->delay_compensation-st->Fs/400)*st->channels], st->Fs/400, dummy, 10); + unsigned char dummy[10]; + celt_encoder_ctl(celt_enc, CELT_RESET_STATE); + celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0)); + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0)); + /* TODO: This wastes CPU a bit compared to just prefilling the buffer */ + celt_encode(celt_enc, &st->delay_buffer[(st->encoder_buffer-st->delay_compensation-st->Fs/400)*st->channels], st->Fs/400, dummy, 10); } else { - celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(2)); + celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(2)); } if (st->mode == MODE_HYBRID) @@ -492,9 +492,9 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, } ec_enc_shrink(&enc, nb_compr_bytes); - } else { - nb_compr_bytes = 0; - } + } else { + nb_compr_bytes = 0; + } for (i=0;i<IMIN(frame_size, st->delay_compensation)*st->channels;i++) pcm_buf[i] = st->delay_buffer[(st->encoder_buffer-st->delay_compensation)*st->channels+i]; @@ -558,9 +558,9 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(start_band)); if (st->mode != MODE_SILK_ONLY) - { - 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); + } /* 5 ms redundant frame for SILK->CELT */ if (redundancy && !celt_to_silk) @@ -587,20 +587,20 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, } else { int tmp = st->encoder_buffer-frame_size; for (i=0;i<tmp*st->channels;i++) - st->delay_buffer[i] = st->delay_buffer[i+frame_size*st->channels]; + st->delay_buffer[i] = st->delay_buffer[i+frame_size*st->channels]; for (i=0;i<frame_size*st->channels;i++) - st->delay_buffer[tmp*st->channels+i] = pcm[i]; + st->delay_buffer[tmp*st->channels+i] = pcm[i]; } - /* Signalling the mode in the first byte */ - data--; - framerate = st->Fs/frame_size; - period = 0; - while (framerate < 400) - { - framerate <<= 1; - period++; - } + /* 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) { data[0] = (silk_internal_bandwidth-OPUS_BANDWIDTH_NARROWBAND)<<5; @@ -634,7 +634,7 @@ int opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size, int opus_encoder_ctl(OpusEncoder *st, int request, ...) { - CELTEncoder *celt_enc; + CELTEncoder *celt_enc; va_list ap; va_start(ap, request); @@ -823,7 +823,7 @@ bad_arg: void opus_encoder_destroy(OpusEncoder *st) { - free(st); + free(st); } int opus_encoder_get_final_range(OpusEncoder *st) diff --git a/src/opus_encoder.h b/src/opus_encoder.h index 7900835714693f5be92c3ef68b8771a78361c23b..73e862e11d947bcf9ae7772d2403de1157087c0a 100644 --- a/src/opus_encoder.h +++ b/src/opus_encoder.h @@ -36,21 +36,21 @@ #define MAX_ENCODER_BUFFER 480 struct OpusEncoder { - int celt_enc_offset; - int silk_enc_offset; - silk_EncControlStruct silk_mode; + int celt_enc_offset; + int silk_enc_offset; + silk_EncControlStruct silk_mode; int hybrid_stereo_width_Q14; - int channels; - int stream_channels; + int channels; + int stream_channels; int force_mono; int mode; int user_mode; int prev_mode; int signal_type; - int bandwidth; - int user_bandwidth; - int voice_ratio; + int bandwidth; + int user_bandwidth; + int voice_ratio; /* Sampling rate (at the API level) */ int Fs; int use_vbr; @@ -67,4 +67,3 @@ struct OpusEncoder { #endif /* OPUS_ENCODER_H */ - diff --git a/src/test_opus.c b/src/test_opus.c index 55e1c9e965a6f8bdf49dc070e7134c478eea2429..2771cb693b3cb3780d05991eb5baa9c0be053dc1 100644 --- a/src/test_opus.c +++ b/src/test_opus.c @@ -40,7 +40,7 @@ #define MAX_PACKET 1500 -void print_usage( char* argv[] ) +void print_usage( char* argv[] ) { fprintf(stderr, "Usage: %s [-e | -d] <application (0/1)> <sampling rate (Hz)> <channels (1/2)> " "<bits per second> [options] <input> <output>\n\n", argv[0]); @@ -61,10 +61,10 @@ void print_usage( char* argv[] ) } #ifdef _WIN32 -# define STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y) +# define STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y) #else -# define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y) -#endif +# define STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y) +#endif static void int_to_char(opus_uint32 i, unsigned char ch[4]) { @@ -82,85 +82,85 @@ static opus_uint32 char_to_int(unsigned char ch[4]) int main(int argc, char *argv[]) { - int err; - char *inFile, *outFile; - FILE *fin, *fout; - OpusEncoder *enc; - OpusDecoder *dec; - int args; - int len[2]; - int frame_size, channels; - int bitrate_bps; - unsigned char *data[2]; - int sampling_rate; - int use_vbr; - int max_payload_bytes; - int complexity; - int use_inbandfec; - int use_dtx; - int forcemono; - int cvbr = 0; - int packet_loss_perc; - int count=0, count_act=0, k; - int skip; - int stop=0; - int tot_read=0, tot_written=0; - short *in, *out; - int application; - double bits=0.0, bits_act=0.0, bits2=0.0, nrg; - int bandwidth=-1; - const char *bandwidth_string; - int write_samples; - int lost = 0, lost_prev = 1; - int toggle = 0; - int enc_final_range[2]; - int encode_only=0, decode_only=0; + int err; + char *inFile, *outFile; + FILE *fin, *fout; + OpusEncoder *enc; + OpusDecoder *dec; + int args; + int len[2]; + int frame_size, channels; + int bitrate_bps; + unsigned char *data[2]; + int sampling_rate; + int use_vbr; + int max_payload_bytes; + int complexity; + int use_inbandfec; + int use_dtx; + int forcemono; + int cvbr = 0; + int packet_loss_perc; + int count=0, count_act=0, k; + int skip; + int stop=0; + int tot_read=0, tot_written=0; + short *in, *out; + int application; + double bits=0.0, bits_act=0.0, bits2=0.0, nrg; + int bandwidth=-1; + const char *bandwidth_string; + int write_samples; + int lost = 0, lost_prev = 1; + int toggle = 0; + int enc_final_range[2]; + int encode_only=0, decode_only=0; - if (argc < 7 ) - { - print_usage( argv ); - return 1; - } + if (argc < 7 ) + { + print_usage( argv ); + return 1; + } - if (strcmp(argv[1], "-e")==0) - { - encode_only = 1; - argv++; - argc--; - } else if (strcmp(argv[1], "-d")==0) - { - decode_only = 1; - argv++; - argc--; - } - application = atoi(argv[1]) + OPUS_APPLICATION_VOIP; - sampling_rate = atoi(argv[2]); - channels = atoi(argv[3]); - bitrate_bps = atoi(argv[4]); + if (strcmp(argv[1], "-e")==0) + { + encode_only = 1; + argv++; + argc--; + } else if (strcmp(argv[1], "-d")==0) + { + decode_only = 1; + argv++; + argc--; + } + application = atoi(argv[1]) + OPUS_APPLICATION_VOIP; + sampling_rate = atoi(argv[2]); + channels = atoi(argv[3]); + bitrate_bps = atoi(argv[4]); - if (sampling_rate != 8000 && sampling_rate != 12000 && sampling_rate != 16000 - && sampling_rate != 24000 && sampling_rate != 48000) - { - fprintf(stderr, "Supported sampling rates are 8000, 12000, 16000, " - "24000 and 48000.\n"); - return 1; - } - frame_size = sampling_rate/50; + if (sampling_rate != 8000 && sampling_rate != 12000 && sampling_rate != 16000 + && sampling_rate != 24000 && sampling_rate != 48000) + { + fprintf(stderr, "Supported sampling rates are 8000, 12000, 16000, " + "24000 and 48000.\n"); + return 1; + } + frame_size = sampling_rate/50; - /* defaults: */ - use_vbr = 1; - bandwidth=OPUS_BANDWIDTH_AUTO; - max_payload_bytes = MAX_PACKET; - complexity = 10; - use_inbandfec = 0; - forcemono = 0; - use_dtx = 0; - packet_loss_perc = 0; - int max_frame_size = 960*3; + /* defaults: */ + use_vbr = 1; + bandwidth = OPUS_BANDWIDTH_AUTO; + max_payload_bytes = MAX_PACKET; + complexity = 10; + use_inbandfec = 0; + forcemono = 0; + use_dtx = 0; + packet_loss_perc = 0; + int max_frame_size = 960*3; - args = 5; - while( args < argc - 2 ) { - /* process command line options */ + args = 5; + while( args < argc - 2 ) { + /* process command line options */ if( STR_CASEINSENSITIVE_COMPARE( argv[ args ], "-cbr" ) == 0 ) { use_vbr = 0; args++; @@ -224,221 +224,221 @@ int main(int argc, char *argv[]) print_usage( argv ); return 1; } - } + } - if( application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO) { - fprintf (stderr, "mode must be: 0 or 1\n"); - return 1; - } + if( application < OPUS_APPLICATION_VOIP || application > OPUS_APPLICATION_AUDIO) { + fprintf (stderr, "mode must be: 0 or 1\n"); + return 1; + } - if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET) - { - fprintf (stderr, "max_payload_bytes must be between 0 and %d\n", - MAX_PACKET); - return 1; - } - if (bitrate_bps < 0 || bitrate_bps*frame_size/sampling_rate > max_payload_bytes*8) - { - fprintf (stderr, "bytes per packet must be between 0 and %d\n", - max_payload_bytes); - return 1; - } + if (max_payload_bytes < 0 || max_payload_bytes > MAX_PACKET) + { + fprintf (stderr, "max_payload_bytes must be between 0 and %d\n", + MAX_PACKET); + return 1; + } + if (bitrate_bps < 0 || bitrate_bps*frame_size/sampling_rate > max_payload_bytes*8) + { + fprintf (stderr, "bytes per packet must be between 0 and %d\n", + max_payload_bytes); + return 1; + } - inFile = argv[argc-2]; - fin = fopen(inFile, "rb"); - if (!fin) - { - fprintf (stderr, "Could not open input file %s\n", argv[argc-2]); - return 1; - } - outFile = argv[argc-1]; - fout = fopen(outFile, "wb+"); - if (!fout) - { - fprintf (stderr, "Could not open output file %s\n", argv[argc-1]); - return 1; - } + inFile = argv[argc-2]; + fin = fopen(inFile, "rb"); + if (!fin) + { + fprintf (stderr, "Could not open input file %s\n", argv[argc-2]); + return 1; + } + outFile = argv[argc-1]; + fout = fopen(outFile, "wb+"); + if (!fout) + { + fprintf (stderr, "Could not open output file %s\n", argv[argc-1]); + return 1; + } - enc = opus_encoder_create(sampling_rate, channels, application); - dec = opus_decoder_create(sampling_rate, channels); + enc = opus_encoder_create(sampling_rate, channels, application); + dec = opus_decoder_create(sampling_rate, channels); - if (enc==NULL) - { - fprintf(stderr, "Failed to create an encoder\n"); - exit(1); - } - if (dec==NULL) - { - fprintf(stderr, "Failed to create a decoder\n"); - exit(1); - } + if (enc==NULL) + { + fprintf(stderr, "Failed to create an encoder\n"); + exit(1); + } + if (dec==NULL) + { + fprintf(stderr, "Failed to create a decoder\n"); + exit(1); + } - opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps)); - 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_CONSTRAINT(cvbr)); - opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); - opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec)); - opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono)); - opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx)); - opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc)); + opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps)); + 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_CONSTRAINT(cvbr)); + opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity)); + opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec)); + opus_encoder_ctl(enc, OPUS_SET_FORCE_MONO(forcemono)); + opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx)); + opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc)); - skip = 5*sampling_rate/1000; - /* When SILK resamples, add 18 samples delay */ - /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000) - skip += 18;*/ + skip = 5*sampling_rate/1000; + /* When SILK resamples, add 18 samples delay */ + /*if (mode != MODE_SILK_ONLY || sampling_rate > 16000) + skip += 18;*/ - switch(bandwidth) - { - case OPUS_BANDWIDTH_NARROWBAND: - bandwidth_string = "narrowband"; - break; - case OPUS_BANDWIDTH_MEDIUMBAND: - bandwidth_string = "mediumband"; - break; - case OPUS_BANDWIDTH_WIDEBAND: - bandwidth_string = "wideband"; - break; - case OPUS_BANDWIDTH_SUPERWIDEBAND: - bandwidth_string = "superwideband"; - break; - case OPUS_BANDWIDTH_FULLBAND: - bandwidth_string = "fullband"; - break; - case OPUS_BANDWIDTH_AUTO: - bandwidth_string = "auto"; - break; - default: - bandwidth_string = "unknown"; - } + switch(bandwidth) + { + case OPUS_BANDWIDTH_NARROWBAND: + bandwidth_string = "narrowband"; + break; + case OPUS_BANDWIDTH_MEDIUMBAND: + bandwidth_string = "mediumband"; + break; + case OPUS_BANDWIDTH_WIDEBAND: + bandwidth_string = "wideband"; + break; + case OPUS_BANDWIDTH_SUPERWIDEBAND: + bandwidth_string = "superwideband"; + break; + case OPUS_BANDWIDTH_FULLBAND: + bandwidth_string = "fullband"; + break; + case OPUS_BANDWIDTH_AUTO: + bandwidth_string = "auto"; + break; + default: + bandwidth_string = "unknown"; + } - fprintf(stderr, "Encoding %d Hz input at %.3f kb/s in %s mode with %d-sample frames.\n", sampling_rate, bitrate_bps*0.001, bandwidth_string, frame_size); + fprintf(stderr, "Encoding %d Hz input at %.3f kb/s in %s mode with %d-sample frames.\n", sampling_rate, bitrate_bps*0.001, bandwidth_string, frame_size); - in = (short*)malloc(frame_size*channels*sizeof(short)); - out = (short*)malloc(max_frame_size*channels*sizeof(short)); - data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char)); - if( use_inbandfec ) { - data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char)); - } - while (!stop) - { - if (decode_only) - { - unsigned char ch[4]; - err = fread(ch, 1, 4, fin); - len[toggle] = char_to_int(ch); - if (len[toggle]>max_payload_bytes || len[toggle]<0) - { - fprintf(stderr, "Invalid payload length\n"); - break; - } - err = fread(ch, 1, 4, fin); - enc_final_range[toggle] = char_to_int(ch); - err = fread(data[toggle], 1, len[toggle], fin); - if (feof(fin)) - break; - tot_read += frame_size*channels; - } else { - err = fread(in, sizeof(short), frame_size*channels, fin); - tot_read += err; - if (err < frame_size*channels) - { - int i; - for (i=err;i<frame_size*channels;i++) - in[i] = 0; - stop = 1; - } + in = (short*)malloc(frame_size*channels*sizeof(short)); + out = (short*)malloc(max_frame_size*channels*sizeof(short)); + data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char)); + if ( use_inbandfec ) { + data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char)); + } + while (!stop) + { + if (decode_only) + { + unsigned char ch[4]; + err = fread(ch, 1, 4, fin); + len[toggle] = char_to_int(ch); + if (len[toggle]>max_payload_bytes || len[toggle]<0) + { + fprintf(stderr, "Invalid payload length\n"); + break; + } + err = fread(ch, 1, 4, fin); + enc_final_range[toggle] = char_to_int(ch); + err = fread(data[toggle], 1, len[toggle], fin); + if (feof(fin)) + break; + tot_read += frame_size*channels; + } else { + err = fread(in, sizeof(short), frame_size*channels, fin); + tot_read += err; + if (err < frame_size*channels) + { + int i; + for (i=err;i<frame_size*channels;i++) + in[i] = 0; + stop = 1; + } - len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes); - enc_final_range[toggle] = opus_encoder_get_final_range( enc ); - if (len[toggle] < 0) - { - fprintf (stderr, "opus_encode() returned %d\n", len[toggle]); - return 1; - } - } + len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes); + enc_final_range[toggle] = opus_encoder_get_final_range( enc ); + if (len[toggle] < 0) + { + fprintf (stderr, "opus_encode() returned %d\n", len[toggle]); + return 1; + } + } - if (encode_only) - { - unsigned char int_field[4]; - int_to_char(len[toggle], int_field); - fwrite(int_field, 1, 4, fout); - int_to_char(enc_final_range[toggle], int_field); - fwrite(int_field, 1, 4, fout); - fwrite(data[toggle], 1, len[toggle], fout); - } else { - int output_samples; - lost = rand()%100 < packet_loss_perc || len[toggle]==0; - if( count >= use_inbandfec ) { - /* delay by one packet when using in-band FEC */ - if( use_inbandfec ) { - if( lost_prev ) { - /* attempt to decode with in-band FEC from next packet */ - output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1); - } else { - /* regular decode */ - output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0); - } - } else { - output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0); - } - if (output_samples>0) - { - write_samples = output_samples-skip; - tot_written += write_samples*channels; - if (tot_written > tot_read) - { - write_samples -= (tot_written-tot_read)/channels; - } - fwrite(out+skip, sizeof(short), write_samples*channels, fout); - skip = 0; - } - } - } + if (encode_only) + { + unsigned char int_field[4]; + int_to_char(len[toggle], int_field); + fwrite(int_field, 1, 4, fout); + int_to_char(enc_final_range[toggle], int_field); + fwrite(int_field, 1, 4, fout); + fwrite(data[toggle], 1, len[toggle], fout); + } else { + int output_samples; + lost = rand()%100 < packet_loss_perc || len[toggle]==0; + if( count >= use_inbandfec ) { + /* delay by one packet when using in-band FEC */ + if( use_inbandfec ) { + if( lost_prev ) { + /* attempt to decode with in-band FEC from next packet */ + output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 1); + } else { + /* regular decode */ + output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, max_frame_size, 0); + } + } else { + output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, max_frame_size, 0); + } + if (output_samples>0) + { + write_samples = output_samples-skip; + tot_written += write_samples*channels; + if (tot_written > tot_read) + { + write_samples -= (tot_written-tot_read)/channels; + } + fwrite(out+skip, sizeof(short), write_samples*channels, fout); + skip = 0; + } + } + } - /* compare final range encoder rng values of encoder and decoder */ - if( !encode_only && !lost && !lost_prev - && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) { - fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count); - return 0; - } + /* compare final range encoder rng values of encoder and decoder */ + if( !encode_only && !lost && !lost_prev && + opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) { + fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder in frame %d.\n", count); + return 0; + } - lost_prev = lost; + lost_prev = lost; - /* count bits */ - bits += len[toggle]*8; - if( count >= use_inbandfec ) { - nrg = 0.0; - if (!decode_only) - { - for ( k = 0; k < frame_size * channels; k++ ) { - nrg += in[ k ] * (double)in[ k ]; - } - } - if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) { - bits_act += len[toggle]*8; - count_act++; - } - /* Variance */ - bits2 += len[toggle]*len[toggle]*64; - } - count++; - toggle = (toggle + use_inbandfec) & 1; - } - fprintf (stderr, "average bitrate: %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count)); - fprintf (stderr, "active bitrate: %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act)); - fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size); - /* Close any files to which intermediate results were stored */ - SILK_DEBUG_STORE_CLOSE_FILES - silk_TimerSave("opus_timing.txt"); - opus_encoder_destroy(enc); - opus_decoder_destroy(dec); - free(data[0]); - if (use_inbandfec) - free(data[1]); - fclose(fin); - fclose(fout); - free(in); - free(out); - return 0; + /* count bits */ + bits += len[toggle]*8; + if( count >= use_inbandfec ) { + nrg = 0.0; + if (!decode_only) + { + for ( k = 0; k < frame_size * channels; k++ ) { + nrg += in[ k ] * (double)in[ k ]; + } + } + if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) { + bits_act += len[toggle]*8; + count_act++; + } + /* Variance */ + bits2 += len[toggle]*len[toggle]*64; + } + count++; + toggle = (toggle + use_inbandfec) & 1; + } + fprintf (stderr, "average bitrate: %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count)); + fprintf (stderr, "active bitrate: %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act)); + fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size); + /* Close any files to which intermediate results were stored */ + SILK_DEBUG_STORE_CLOSE_FILES + silk_TimerSave("opus_timing.txt"); + opus_encoder_destroy(enc); + opus_decoder_destroy(dec); + free(data[0]); + if (use_inbandfec) + free(data[1]); + fclose(fin); + fclose(fout); + free(in); + free(out); + return 0; }