From 1f65994ef428520534630d5d706c91fb1d690938 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin <jmvalin@jmvalin.ca> Date: Sun, 9 Oct 2011 01:05:25 -0400 Subject: [PATCH] Avoids unnecessary collapse of the HF stereo image in hybrid mode. SILK now reports an "effective width" that takes into account side prediction. --- silk/enc_API.c | 2 +- silk/stereo_LR_to_MS.c | 15 +++++++++++++++ silk/structs.h | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/silk/enc_API.c b/silk/enc_API.c index 4702401b4..cd4d960cb 100644 --- a/silk/enc_API.c +++ b/silk/enc_API.c @@ -452,7 +452,7 @@ opus_int silk_Encode( encControl->allowBandwidthSwitch = psEnc->allowBandwidthSwitch; encControl->inWBmodeWithoutVariableLP = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == 16 && psEnc->state_Fxx[ 0 ].sCmn.sLP.mode == 0; encControl->internalSampleRate = silk_SMULBB( psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, 1000 ); - encControl->stereoWidth_Q14 = psEnc->sStereo.width_prev_Q14; + encControl->stereoWidth_Q14 = psEnc->sStereo.effective_width_prev_Q14; if( prefillFlag ) { encControl->payloadSize_ms = tmp_payloadSize_ms; encControl->complexity = tmp_complexity; diff --git a/silk/stereo_LR_to_MS.c b/silk/stereo_LR_to_MS.c index 7fbb3ae7a..24f4800c5 100644 --- a/silk/stereo_LR_to_MS.c +++ b/silk/stereo_LR_to_MS.c @@ -53,6 +53,7 @@ void silk_stereo_LR_to_MS( opus_int16 LP_mid[ MAX_FRAME_LENGTH ], HP_mid[ MAX_FRAME_LENGTH ]; opus_int16 LP_side[ MAX_FRAME_LENGTH ], HP_side[ MAX_FRAME_LENGTH ]; opus_int16 *mid = &x1[ -2 ]; + opus_int16 effective_pred=0; /* Convert to basic mid/side signals */ for( n = 0; n < frame_length + 2; n++ ) { @@ -139,6 +140,7 @@ void silk_stereo_LR_to_MS( silk_stereo_quant_pred( pred_Q13, ix ); /* Collapse stereo width */ width_Q14 = 0; + effective_pred = silk_abs( pred_Q13[ 0 ] ) + silk_abs( pred_Q13[ 1 ] ); pred_Q13[ 0 ] = 0; pred_Q13[ 1 ] = 0; mid_side_rates_bps[ 0 ] = total_rate_bps; @@ -154,6 +156,7 @@ void silk_stereo_LR_to_MS( silk_stereo_quant_pred( pred_Q13, ix ); /* Collapse stereo width */ width_Q14 = 0; + effective_pred = silk_abs( pred_Q13[ 0 ] ) + silk_abs( pred_Q13[ 1 ] ); pred_Q13[ 0 ] = 0; pred_Q13[ 1 ] = 0; } else if( state->smth_width_Q14 > SILK_FIX_CONST( 0.95, 14 ) ) { @@ -166,6 +169,7 @@ void silk_stereo_LR_to_MS( pred_Q13[ 1 ] = silk_RSHIFT( silk_SMULBB( state->smth_width_Q14, pred_Q13[ 1 ] ), 14 ); silk_stereo_quant_pred( pred_Q13, ix ); width_Q14 = state->smth_width_Q14; + effective_pred = silk_abs( pred_Q13[ 0 ] ) + silk_abs( pred_Q13[ 1 ] ); } if (*mid_only_flag == 0 && mid_side_rates_bps[ 1 ] < 1) @@ -210,4 +214,15 @@ void silk_stereo_LR_to_MS( state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ]; state->pred_prev_Q13[ 1 ] = (opus_int16)pred_Q13[ 1 ]; state->width_prev_Q14 = (opus_int16)width_Q14; + { + /* Evaluate the effective width of the SILK stereo so we can report it + for the CELT layer to partially collapse the image. We need to take + into account the prediction otherwise we risk compeltely collapsing + the HF image when doing panned mono */ + opus_int32 effective_width; + effective_width = (opus_int32)state->width_prev_Q14 + silk_LSHIFT32( (opus_int32)effective_pred, 1); + effective_width += silk_RSHIFT( effective_width, 2 ); + effective_width = silk_min_32(effective_width, 16384); + state->effective_width_prev_Q14 = effective_width; + } } diff --git a/silk/structs.h b/silk/structs.h index 70c81baee..10a3546c5 100644 --- a/silk/structs.h +++ b/silk/structs.h @@ -101,6 +101,7 @@ typedef struct { opus_int32 mid_side_amp_Q0[ 4 ]; opus_int16 smth_width_Q14; opus_int16 width_prev_Q14; + opus_int16 effective_width_prev_Q14; opus_int8 predIx[ MAX_FRAMES_PER_PACKET ][ 2 ][ 3 ]; opus_int8 mid_only_flags[ MAX_FRAMES_PER_PACKET ]; } stereo_enc_state; -- GitLab