diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2012-07-12 17:36:11 -0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2012-07-12 17:36:11 -0400 |
commit | ca317e700cdbdaeda74e030dfaf8029ddec75d6d (patch) | |
tree | 4ee4917d3d6862ebbb16a163c21a6e3e404a67bc | |
parent | e39f244a7c5196ff6f83f452f9ed701854056ae4 (diff) | |
download | opus-exp_koen4.tar.gz |
Fixes the high-band hybrid gain from the previous commitexp_koen4
Adds a gain cross-fade to avoid discontinuities and moves it
to a place where it won't affect SILK
-rw-r--r-- | src/opus_encoder.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/src/opus_encoder.c b/src/opus_encoder.c index 546fe134..509fcab4 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -79,6 +79,7 @@ struct OpusEncoder { int stream_channels; opus_int16 hybrid_stereo_width_Q14; opus_int32 variable_HP_smth2_Q15; + opus_val16 prev_HB_gain; opus_val32 hp_mem[4]; int mode; int prev_mode; @@ -217,6 +218,7 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat st->delay_compensation = st->Fs/250; st->hybrid_stereo_width_Q14 = 1 << 14; + st->prev_HB_gain = Q15ONE; st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ); st->first = 1; st->mode = MODE_HYBRID; @@ -399,6 +401,30 @@ static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, op } } +static void gain_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2, + int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs) +{ + int i; + int inc; + int overlap; + inc = 48000/Fs; + overlap=overlap48/inc; + for (i=0;i<overlap;i++) + { + opus_val16 g, w; + w = MULT16_16_Q15(window[i*inc], window[i*inc]); + g = SHR32(MAC16_16(MULT16_16(w,g2), + Q15ONE-w, g1), 15); + out[i*channels] = MULT16_16_Q15(g, in[i*channels]); + out[i*channels+1] = MULT16_16_Q15(g, in[i*channels+1]); + } + for (;i<frame_size;i++) + { + out[i*channels] = MULT16_16_Q15(g2, in[i*channels]); + out[i*channels+1] = MULT16_16_Q15(g2, in[i*channels+1]); + } +} + OpusEncoder *opus_encoder_create(opus_int32 Fs, int channels, int application, int *error) { int ret; @@ -473,6 +499,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size, int frame_rate; opus_int32 max_rate; int curr_bandwidth; + opus_val16 HB_gain; VARDECL(opus_val16, tmp_prefill); ALLOC_STACK; @@ -840,9 +867,10 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size, } /* SILK processing */ + HB_gain = Q15ONE; if (st->mode != MODE_CELT_ONLY) { - opus_int32 total_bitRate, celt_rate, HB_gain_Q16; + opus_int32 total_bitRate, celt_rate; #ifdef FIXED_POINT const opus_int16 *pcm_silk; #else @@ -853,6 +881,7 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size, /* Distribute bits between SILK and CELT */ total_bitRate = 8 * bytes_target * frame_rate; if( st->mode == MODE_HYBRID ) { + int HB_gain_ref; /* Base rate for SILK */ st->silk_mode.bitRate = st->stream_channels * ( 5000 + 1000 * ( st->Fs == 100 * frame_size ) ); if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) { @@ -868,11 +897,8 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size, } /* Increasingly attenuate high band when it gets allocated fewer bits */ celt_rate = total_bitRate - st->silk_mode.bitRate; - if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) { - HB_gain_Q16 = ( celt_rate << 10 ) / ( ( celt_rate + st->stream_channels * 2000 ) >> 6 ); - } else { /* FULLBAND */ - HB_gain_Q16 = ( celt_rate << 10 ) / ( ( celt_rate + st->stream_channels * 2400 ) >> 6 ); - } + HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 2000 : 2400; + HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels*HB_gain_ref, 6); } else { /* SILK gets all bits */ st->silk_mode.bitRate = total_bitRate; @@ -985,19 +1011,6 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size, celt_to_silk = 0; st->silk_bw_switch = 1; } - - if( st->mode == MODE_HYBRID ) { -#ifdef FIXED_POINT - for (i=0;i<frame_size*st->channels;i++) { - pcm_buf[delay_compensation*st->channels + i] = (opus_val16)( ( HB_gain_Q16 * pcm_buf[delay_compensation*st->channels + i] ) >> 16 ); - } -#else - float HB_gain = HB_gain_Q16 / 65536.0f; - for (i=0;i<frame_size*st->channels;i++) { - pcm_buf[delay_compensation*st->channels + i] *= HB_gain; - } -#endif - } } /* CELT processing */ @@ -1071,7 +1084,16 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size, for (;i<st->encoder_buffer*st->channels;i++) st->delay_buffer[i] = pcm_buf[(frame_size+delay_compensation-st->encoder_buffer)*st->channels+i]; + /* gain_fade() and stereo_fade() need to be after the buffer copying + because we don't want any of this to affect the SILK part */ + if( st->prev_HB_gain < Q15ONE || HB_gain < Q15ONE ) { + const CELTMode *celt_mode; + celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode)); + gain_fade(pcm_buf, pcm_buf, + st->prev_HB_gain, HB_gain, celt_mode->overlap, frame_size, st->channels, celt_mode->window, st->Fs); + } + st->prev_HB_gain = HB_gain; if (st->mode != MODE_HYBRID || st->stream_channels==1) st->silk_mode.stereoWidth_Q14 = 1<<14; if( st->channels == 2 ) { @@ -1532,6 +1554,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...) silk_InitEncoder( silk_enc, &dummy ); st->stream_channels = st->channels; st->hybrid_stereo_width_Q14 = 1 << 14; + st->prev_HB_gain = Q15ONE; st->first = 1; st->mode = MODE_HYBRID; st->bandwidth = OPUS_BANDWIDTH_FULLBAND; |