diff options
author | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2012-07-13 01:36:11 +0400 |
---|---|---|
committer | Jean-Marc Valin <jmvalin@jmvalin.ca> | 2012-10-10 21:44:26 +0400 |
commit | f68799b20859113870f54e84244dff808526f324 (patch) | |
tree | 28ce14114e275156f40395de16e108b1b4194d7f /src | |
parent | 0b00b3196713305443080aaf35f1ddc05ce94306 (diff) |
Fixes the high-band hybrid gain from the previous commit
Adds a gain cross-fade to avoid discontinuities and moves it
to a place where it won't affect SILK
Conflicts:
src/opus_encoder.c
Diffstat (limited to 'src')
-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 61bddc2b..3762a1e9 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -75,6 +75,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; @@ -215,6 +216,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; @@ -450,6 +452,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; @@ -524,6 +550,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s int frame_rate; opus_int32 max_rate; /* Max bitrate we're allowed to use */ int curr_bandwidth; + opus_val16 HB_gain; opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */ int extra_buffer, total_buffer; int perform_analysis=0; @@ -944,9 +971,10 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s #endif /* 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 @@ -957,6 +985,7 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s /* 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 ) { @@ -972,11 +1001,8 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s } /* 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; @@ -1089,19 +1115,6 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s 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 */ @@ -1175,7 +1188,16 @@ opus_int32 opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_s for (;i<st->encoder_buffer*st->channels;i++) st->delay_buffer[i] = pcm_buf[(frame_size+total_buffer-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 ) { @@ -1686,6 +1708,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; |