diff --git a/lib_com/options.h b/lib_com/options.h old mode 100644 new mode 100755 index c357e4d4dd2e9b3c620b3af24d3826d88fc7f4ac..9d70b5d1ecef36bc81a32e18e597e971ba1b0176 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -134,6 +134,11 @@ #define FIX_1521_SBA_LOUDNESS_STEREO /* FhG: issue 1521: Fix loudness for SBA to stereo rendering */ #define FIX_1559 /* Eri/FhG: fix for Issue 1559 in FD CNG with bitrate/bw switching */ +/* Macros for issue 1966 are independent, phase diff is always BE for EVS_MONO */ +/* The changes for F0+thdModification are mainly for IVAS better float compatibility, */ +/* for EVS_MONO, all is kept BE. */ +#define FIX_ISSUE_1966_PHASE_DIFF /* FhG: Basop issue 1966: shift phase range to [-2PI..+2PI[, handle 4 quadrants */ +#define FIX_ISSUE_1966_F0_32BIT /* FhG: Basop issue 1966: use 32-bit variables for F0 and thresholdModification */ /* ##################### End NON-BE switches ########################### */ /* ################## End MAINTENANCE switches ######################### */ diff --git a/lib_dec/TonalComponentDetection_fx.c b/lib_dec/TonalComponentDetection_fx.c index 2223bfa9cf5be67544a660dd0d6034e3a6b41576..b5718956cb3d4483947cc4867fc8e71265f1030c 100644 --- a/lib_dec/TonalComponentDetection_fx.c +++ b/lib_dec/TonalComponentDetection_fx.c @@ -12,21 +12,36 @@ #include "prot_fx.h" #include "ivas_prot_fx.h" - /*---------------------------------------------------------------------* * Local function prototypes *---------------------------------------------------------------------*/ +/* Note: + * This version of the module is a hybrid variant, that processes in 2 modes: + * EVS_MONO: works with 16-bit F0 and 16-bit thresholdModification[] + * other: works with 32-bit F0-32 and 32-bit thresholdModification32[] + */ + static void calcPseudoSpec( const Word32 *mdctSpec, const Word16 mdctSpec_exp, const Word16 nSamples, Word16 floorPowerSpectrum, Word32 *powerSpec, Word16 *powerSpec_exp ); static void getEnvelope( const Word16 nSamples, const Word32 *powerSpec, Word16 F0, Word32 *envelope, Word32 *smoothedSpectrum ); -static void GetF0( Word16 const nSamples, Word16 const nSamplesCore, Word32 const *const powerSpectrum, Word32 const pitchLag, Word16 *const pOrigF0, Word16 *const pF0 ); static void findStrongestHarmonics( const Word16 nSamples, const Word32 *powerSpectrum, const Word16 F0, const Word16 nTotalHarmonics, Word16 *pHarmonicIndexes, Word16 *pnHarmonics ); +#ifdef FIX_ISSUE_1966_F0_32BIT +static void GetF0( Word16 const nSamples, Word16 const nSamplesCore, Word32 const *const powerSpectrum, Word32 const pitchLag, Word16 *const pOrigF0, Word32 *const pOrigF0_32, Word16 *const pF0, Word32 *const pF0_32, const Word16 element_mode ); +static void CorrectF0( const Word16 *pHarmonicIndexes, const Word16 nHarmonics, Word16 *pF0, Word32 *pF0_32, const Word16 element_mode ); +static void findCandidates( const Word16 nSamples, const Word32 *MDCTSpectrum, const Word16 MDCTSpectrum_exp, Word16 *thresholdModificationNew, Word32 *thresholdModificationNew32, Word16 floorPowerSpectrum, const Word16 element_mode ); +static void modifyThreshold( Word16 i, Word16 F0, Word32 F0_32, Word16 threshold, Word32 threshold_32, Word16 *thresholdModification, Word32 *thresholdModification32, const Word16 element_mode ); +static void modifyThresholds( Word16 F0, Word32 F0_32, Word16 origF0, Word32 origF0_32, Word16 *thresholdModification, Word32 *thresholdModification32, const Word16 element_mode ); +static void RefineThresholdsUsingPitch_fx( const Word16 nSamples, const Word16 nSamplesCore, const Word32 powerSpectrum[], const Word32 lastPitchLag, const Word32 currentPitchLag, Word16 *pF0, Word32 *pF0_32, Word16 *thresholdModification, Word32 *thresholdModification32, const Word16 element_mode ); +static void findTonalComponents_fx( Word16 *indexOfTonalPeak, Word16 *lowerIndex, Word16 *upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 *powerSpectrum, const Word16 powerSpectrum_e, Word16 F0, Word16 *thresholdModification, Word32 *thresholdModification32, const Word16 element_mode ); +#else +static void GetF0( Word16 const nSamples, Word16 const nSamplesCore, Word32 const *const powerSpectrum, Word32 const pitchLag, Word16 *const pOrigF0, Word16 *const pF0 ); static void CorrectF0( const Word16 *pHarmonicIndexes, const Word16 nHarmonics, Word16 *pF0 ); static void findCandidates( const Word16 nSamples, const Word32 *MDCTSpectrum, const Word16 MDCTSpectrum_exp, Word16 *thresholdModificationNew, Word16 floorPowerSpectrum ); static void modifyThreshold( Word16 i, Word16 F0, Word16 threshold, Word16 *thresholdModification ); static void modifyThresholds( Word16 F0, Word16 origF0, Word16 *thresholdModification ); static void RefineThresholdsUsingPitch_fx( const Word16 nSamples, const Word16 nSamplesCore, const Word32 powerSpectrum[], const Word32 lastPitchLag, const Word32 currentPitchLag, Word16 *pF0, Word16 *thresholdModification ); -static void findTonalComponents_fx( Word16 *indexOfTonalPeak, Word16 *lowerIndex, Word16 *upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 *powerSpectrum, const Word16 powerSpectrum_e, Word16 F0, Word16 *thresholdModification, Word16 element_mode ); +static void findTonalComponents_fx( Word16 *indexOfTonalPeak, Word16 *lowerIndex, Word16 *upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 *powerSpectrum, const Word16 powerSpectrum_e, Word16 F0, Word16 *thresholdModification, const Word16 element_mode ); +#endif /*-------------------------------------------------------------------* @@ -60,6 +75,10 @@ void DetectTonalComponents_fx( ) { Word16 F0; +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 F0_32; + Word32 thresholdModification32[L_FRAME_MAX]; +#endif Word16 thresholdModification[L_FRAME_MAX], lastMDCTSpect_exp; Word32 pScaledMdctSpectrum[L_FRAME_MAX]; Word16 nBands; @@ -121,6 +140,22 @@ void DetectTonalComponents_fx( scale_sig32( pScaledMdctSpectrum, nSamples, -1 ); /*q_pScaledMdctSpectrum - 1*/ } +#ifdef FIX_ISSUE_1966_F0_32BIT + /* Find peak candidates in the last frame. */ + findCandidates( nSamples, pScaledMdctSpectrum, lastMDCTSpect_exp, thresholdModification, thresholdModification32, floorPowerSpectrum, element_mode ); + + /* Refine peak candidates using the pitch information */ + RefineThresholdsUsingPitch_fx( nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, &F0_32, + thresholdModification, thresholdModification32, element_mode ); + + /* Find peaks in the second last frame */ + if ( element_mode != EVS_MONO ) + { + F0 = extract_h( F0_32 ); + } + findTonalComponents_fx( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, secondLastPowerSpectrum_e, + F0, thresholdModification, thresholdModification32, element_mode ); +#else /* Find peak candidates in the last frame. */ findCandidates( nSamples, pScaledMdctSpectrum, lastMDCTSpect_exp, thresholdModification, floorPowerSpectrum ); @@ -128,8 +163,9 @@ void DetectTonalComponents_fx( RefineThresholdsUsingPitch_fx( nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, thresholdModification ); /* Find peaks in the second last frame */ - findTonalComponents_fx( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, secondLastPowerSpectrum_e, F0, thresholdModification, element_mode ); - + findTonalComponents_fx( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, secondLastPowerSpectrum_e, + F0, thresholdModification, element_mode ); +#endif return; } @@ -395,7 +431,16 @@ static void GetF0( /*i - Qx */ /*is justed handed over and given back*/ Word32 /*int*/ const pitchLag, /*i - Q16*/ Word16 /*short*/ *const pOrigF0, /*o - Q10*/ - Word16 /*short*/ *const pF0 ) /*o - Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 *const pOrigF0_32, /*o - Q10+16*/ +#endif + Word16 /*short*/ *const pF0 /*o - Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + , + Word32 *const pF0_32, /*o - Q10+16*/ + const Word16 element_mode /*i EVS_MONO or anything else */ +#endif +) { Word16 /*short*/ tmpPitchLag; Word16 /*short*/ rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH]; /*Q0*/ @@ -414,34 +459,91 @@ static void GetF0( = round_fx( L_shl( pitchLag, 4 ) ); /*no division by 2, will be done in following division - furthermore, do a leftshift before rounding, to preserve more accuracy - will be accommodated also in following division*/ - +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( element_mode == EVS_MONO ) + { + /**pF0 = nSamplesCore/tmpPitchLag;*/ + BASOP_Util_Divide_MantExp( nSamplesCore, 0, tmpPitchLag, -( 1 /*division by 2*/ + 4 /*accommodate accuracy-prevention-leftshift*/ ), pF0, &tmp ); /*pF0 is Q15*/ + *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/ + move16(); + *pOrigF0 = *pF0; /*Q10*/ + move16(); + } + ELSE + { + Word16 tmp_32 = 0; + Word32 F0_32 = BASOP_Util_Divide3232_Scale_newton( L_shl( nSamplesCore, Q16 ), tmpPitchLag, &tmp_32 ); + F0_32 = L_shl( F0_32, tmp_32 - Q16 ); + *pF0_32 = F0_32; + move32(); + *pOrigF0_32 = *pF0_32; /*Q26*/ + move32(); + } +#else /**pF0 = nSamplesCore/tmpPitchLag;*/ BASOP_Util_Divide_MantExp( nSamplesCore, 0, tmpPitchLag, -( 1 /*division by 2*/ + 4 /*accommodate accuracy-prevention-leftshift*/ ), pF0, &tmp ); /*pF0 is Q15*/ - move16(); - *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/ + *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/ move16(); *pOrigF0 = *pF0; /*Q10*/ move16(); +#endif + tmp = 2 * LAST_HARMONIC_POS_TO_CHECK; if ( LT_16( nSamples, 2 * LAST_HARMONIC_POS_TO_CHECK ) ) { move16(); tmp = nSamples; } + +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( element_mode == EVS_MONO ) + { + BASOP_Util_Divide_MantExp( tmp, 15, *pF0, 5, &nTotalHarmonics, &tmp ); + nTotalHarmonics = shl( nTotalHarmonics, sub( tmp, 15 ) ); + /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */ + findStrongestHarmonics( nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics ); + CorrectF0( rgiStrongHarmonics, nStrongHarmonics, pF0, NULL, element_mode ); + } + ELSE + { + BASOP_Util_Divide_MantExp( tmp, 15, extract_h( *pF0_32 ), 5, &nTotalHarmonics, &tmp ); + nTotalHarmonics = shl( nTotalHarmonics, sub( tmp, 15 ) ); + + /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */ + findStrongestHarmonics( nSamples, powerSpectrum, extract_h( *pF0_32 ), nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics ); + CorrectF0( rgiStrongHarmonics, nStrongHarmonics, NULL, pF0_32, element_mode ); + } +#else BASOP_Util_Divide_MantExp( tmp, 15, *pF0, 5, &nTotalHarmonics, &tmp ); nTotalHarmonics = shl( nTotalHarmonics, sub( tmp, 15 ) ); - /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */ findStrongestHarmonics( nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics ); - CorrectF0( rgiStrongHarmonics, nStrongHarmonics, pF0 ); +#endif } ELSE { +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( element_mode == EVS_MONO ) + { + move16(); + move16(); + *pF0 = 0; + *pOrigF0 = 0; + } + ELSE + { + move32(); + move32(); + *pF0_32 = 0; + *pOrigF0_32 = 0; + } +#else move16(); move16(); *pF0 = 0; *pOrigF0 = 0; +#endif } return; @@ -537,10 +639,20 @@ static void findStrongestHarmonics( static void CorrectF0( const Word16 /*short*/ *pHarmonicIndexes, /*I - Q0 */ const Word16 /*short*/ nHarmonics, /*I - Q0 */ - Word16 /*short*/ *pF0 ) /*I/O - Q10 range: {0}, [4..18) */ + Word16 /*short*/ *pF0 /*I/O - Q10 range: {0}, [4..18) */ +#ifdef FIX_ISSUE_1966_F0_32BIT + , + Word32 /*long*/ *pF0_32, /*I/O - Q10+16 range: {0}, [4..18), NULL for EVS_MONO */ + const Word16 element_mode /*I EVS_MONO or anything else */ +#endif +) { Word16 /*short*/ i; - Word16 /*short*/ F0; + Word16 /*short*/ F0 = 0; /* init for windows compiler only */ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 /*long*/ F0_32 = 0; /* unused in EVS_MONO */ +#endif + Word16 /*short*/ diff[MAX_PEAKS_FROM_PITCH - 1], sortedDiff[MAX_PEAKS_FROM_PITCH - 1]; /*Q0*/ Word16 /*short*/ iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult; /*Q0*/ @@ -554,10 +666,43 @@ static void CorrectF0( move16(); } +#ifdef FIX_ISSUE_1966_F0_32BIT + /* i = MAX_PEAKS_FROM_PITCH - 1 (9) now */ + IF( element_mode == EVS_MONO ) + { + F0 = *pF0; /*Q10*/ + move16(); + test(); + if ( F0 == 0 || nHarmonics == 0 ) + { + i = 0; /* skip processing */ + move16(); + } + } + ELSE + { + F0_32 = *pF0_32; + move32(); + test(); + if ( F0_32 == 0 || nHarmonics == 0 ) + { + i = 0; /* skip processing */ + move16(); + } + } +#else F0 = *pF0; /*Q10*/ - + move16(); test(); - IF( F0 > 0 && nHarmonics != 0 ) + if ( F0 == 0 || nHarmonics == 0 ) + { + i = 0; /* skip processing */ + move16(); + } + +#endif + + IF( i != 0 ) /* skip processing, if F0=0 or nHarmonics=0 */ { tmp = sub( nHarmonics, 1 ); FOR( i = 0; i < tmp; i++ ) @@ -660,13 +805,37 @@ static void CorrectF0( IF( LE_16( iMult, 3 ) ) { +#ifdef FIX_ISSUE_1966_F0_32BIT /* Use iMostCommonDiff, because the lowest pHarmonicIndexes[i] (which is equal to iMult) may not correspond to the new F0, but to it's multiple */ + IF( element_mode == EVS_MONO ) + { + F0 = round_fx_sat( L_shl_sat( L_mult( iMostCommonDiff /*Q0*/, F0 /*Q10*/ ), 15 ) ); /*Q10*/ + } + ELSE + { + F0_32 = L_shl_sat( Mpy_32_16_1( F0_32 /*Q10+16*/, iMostCommonDiff /*Q0*/ ), 15 ); /*Q10+16*/ + } +#else F0 = round_fx_sat( L_shl_sat( L_mult( iMostCommonDiff /*Q0*/, F0 /*Q10*/ ), 15 ) ); /*Q10*/ +#endif } ELSE { +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( element_mode == EVS_MONO ) + { + F0 = 0; + move16(); + } + ELSE + { + F0_32 = 0; + move32(); + } +#else F0 = 0; move16(); +#endif } } /* Otherwise if there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */ @@ -677,29 +846,97 @@ static void CorrectF0( if ( ( GT_16( iMostCommonDiff, 1 ) ) || ( LT_16( nMostCommonDiff, 3 ) ) ) { /* Not enough peaks at the same distance => don't use the pitch. */ +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( element_mode == EVS_MONO ) + { + F0 = 0; + move16(); + } + ELSE + { + F0_32 = 0; + move32(); + } +#else F0 = 0; move16(); +#endif } } +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( element_mode == EVS_MONO ) + { + *pF0 = F0; + move16(); + } + ELSE + { + *pF0_32 = F0_32; + move32(); + } +#else *pF0 = F0; move16(); +#endif } - return; } static void modifyThreshold( - Word16 /*short*/ i, /*I - Q0 */ - Word16 /*short*/ F0, /*I - Q10*/ - Word16 /*short*/ threshold, /*I - Q10*/ - Word16 * /*short*/ thresholdModification ) /*I/O - Q10*/ + Word16 /*short*/ i, /*I - Q0 */ + Word16 /*short*/ F0, /*I - Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 F0_32, /*I - Q26*/ +#endif + Word16 /*short*/ threshold, /*I - Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 threshold_32, /*I - Q26*/ +#endif + Word16 * /*short*/ thresholdModification /*I - Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + , + Word32 * /*long*/ thresholdModification32, /*I - Q26*/ + const Word16 element_mode /*I/O - Q10*/ +#endif +) { Word32 harmonic; Word16 fractional /*Q15*/; Word16 k /*Q0*/; Word16 twoTimesFract /*Q10*/; +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( EQ_16( element_mode, EVS_MONO ) ) + { + harmonic = L_mult( shl( i, 5 ), F0 ); /*Q0 * Q10 = 15Q16*/ + k = extract_h( harmonic ); /*Q0*/ + fractional = lshr( extract_l( harmonic ), 1 ); /* Fractional part of the i*F0 */ /*Q15*/ + twoTimesFract = mult( 2048 /*2 in Q10*/, fractional /*Q15*/ ); /*Q10*/ /* threshold if the center of the peek is between k-1 and k, threshold+2 if the center of the peek is between k and k+1 */ + + move16(); + thresholdModification[k] = threshold; + move16(); + thresholdModification[k - 1] = add( threshold /*Q10*/, twoTimesFract /*Q10*/ ); /*Q10*/ + move16(); + thresholdModification[k + 1] = add( threshold /*Q10*/, sub( 2048 /*2 in Q10*/, twoTimesFract /*Q10*/ ) /*Q10*/ ); /*Q10*/ + } + ELSE + { + Word32 L_twoTimesFract /*Q10+16*/; + harmonic = Mpy_32_16_1( F0_32, shl( i, 5 ) ); /*Q0 * Q10 = 15Q16*/ + k = extract_h( harmonic ); /*Q0*/ + fractional = lshr( extract_l( harmonic ), 1 ); /* Fractional part of the i*F0 */ /*Q15*/ + L_twoTimesFract = L_mult( 2048 /*2 in Q10*/, fractional /*Q15*/ ); /*Q10+16*/ /* threshold if the center of the peek is between k-1 and k, threshold+2 if the center of the peek is between k and k+1 */ + + move32(); + thresholdModification32[k] = threshold_32; /*Q10+16*/ + move32(); + thresholdModification32[k - 1] = L_add( threshold_32 /*Q10+16*/, L_twoTimesFract /*Q10+16*/ ); /*Q10+16*/ + move32(); + thresholdModification32[k + 1] = L_add( threshold_32 /*Q10+16*/, L_sub( 2048 << 16 /*2 in Q10+16*/, L_twoTimesFract /*Q10*/ ) /*Q10*/ ); /*Q10*/ + } +#else harmonic = L_mult( shl( i, 5 ), F0 ); /*Q0 * Q10 = 15Q16*/ k = extract_h( harmonic ); /*Q0*/ fractional = lshr( extract_l( harmonic ), 1 ); /* Fractional part of the i*F0 */ /*Q15*/ @@ -711,19 +948,41 @@ static void modifyThreshold( thresholdModification[k - 1] = add( threshold /*Q10*/, twoTimesFract /*Q10*/ ); /*Q10*/ move16(); thresholdModification[k + 1] = add( threshold /*Q10*/, sub( 2048 /*2 in Q10*/, twoTimesFract /*Q10*/ ) /*Q10*/ ); /*Q10*/ - +#endif return; } static void modifyThresholds( - Word16 /*short*/ F0, /*I - Q10*/ - Word16 /*short*/ origF0, /*I - Q10*/ - Word16 * /*short*/ thresholdModification ) /*I/O - Q10*/ + Word16 /*short*/ F0, /*I - Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 F0_32, /*I - Q26*/ +#endif + Word16 /*short*/ origF0, /*I - Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 origF0_32, /*I - Q26*/ +#endif + Word16 * /*short*/ thresholdModification /*Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + , + Word32 * /*long*/ thresholdModification32, /*Q26*/ + const Word16 element_mode /*I EVS_MONO or anything else */ +#endif +) { Word16 /*int*/ i, /*int*/ nHarmonics; Word16 tmp, tmpM, tmpE; +#ifdef FIX_ISSUE_1966_F0_32BIT + /* Note: in case besides EVS_MONO, we set the 16-bit variables */ + /* accordingly and control further processing with those. */ + IF( element_mode != EVS_MONO ) + { + origF0 = extract_h( origF0_32 ); + F0 = extract_h( F0_32 ); + } +#endif + IF( origF0 > 0 ) { IF( F0 == 0 ) @@ -732,7 +991,14 @@ static void modifyThresholds( FOR( i = 1; i <= nHarmonics; i++ ) { - modifyThreshold( i, origF0, 717 /*0.7f Q10*/ /*0.7f in Q10*/, thresholdModification ); +#ifdef FIX_ISSUE_1966_F0_32BIT + modifyThreshold( i, origF0, origF0_32, + 717 /*0.7f in Q10*/, 46976205 /*0.7f in Q10+16*/, + thresholdModification, thresholdModification32, + element_mode ); +#else + modifyThreshold( i, origF0, 717 /*0.7f in Q10*/, thresholdModification ); +#endif } } IF( F0 > 0 ) @@ -745,11 +1011,25 @@ static void modifyThresholds( FOR( i = tmp; i > 0; i-- ) { - modifyThreshold( i, origF0, 358 /*0.35f Q10*/, thresholdModification ); +#ifdef FIX_ISSUE_1966_F0_32BIT + modifyThreshold( i, origF0, origF0_32, + 358 /*0.35f in Q10*/, 23488102 /*0.35 in Q10+16*/, + thresholdModification, thresholdModification32, + element_mode ); +#else + modifyThreshold( i, origF0, 358 /*0.35f in Q10*/, thresholdModification ); +#endif } FOR( i = 1; i <= nHarmonics; i++ ) { +#ifdef FIX_ISSUE_1966_F0_32BIT + modifyThreshold( i, F0, F0_32, + 358 /*0.35f Q10*/, 23488102 /*0.35 in Q10+16*/, + thresholdModification, thresholdModification32, + element_mode ); +#else modifyThreshold( i, F0, 358 /*0.35f Q10*/, thresholdModification ); +#endif } } } @@ -763,7 +1043,13 @@ static void findCandidates( const Word32 *MDCTSpectrum, /* i : MDCT spectrum */ const Word16 MDCTSpectrum_exp, /* i : exponent of MDCT spectrum */ Word16 *thresholdModificationNew, /* o : threshold modification Q10 */ - Word16 floorPowerSpectrum /* i : lower limit for power spectrum bins Q0*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 *thresholdModificationNew32, /* o : threshold modification Q10+Q16 */ + Word16 floorPowerSpectrum, /* i : lower limit for powerspectrum bins Q0*/ + const Word16 element_mode /* i : EVS_MONO or anything else */ +#else + Word16 floorPowerSpectrum /* i : lower limit for powerspectrum bins Q0*/ +#endif ) { Word32 powerSpectrum[L_FRAME_MAX]; @@ -776,10 +1062,19 @@ static void findCandidates( Word16 tmp_loop1, tmp_loop2, tmp_loop3; calcPseudoSpec( MDCTSpectrum, MDCTSpectrum_exp, nSamples, floorPowerSpectrum, powerSpectrum, &powerSpectrum_exp ); - getEnvelope( nSamples, powerSpectrum, 0, envelope, smoothedSpectrum ); - +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( EQ_16( element_mode, EVS_MONO ) ) + { + set16_fx( thresholdModificationNew, UNREACHABLE_THRESHOLD, nSamples ); /*Q10*/ + } + ELSE + { + set32_fx( thresholdModificationNew32, ( UNREACHABLE_THRESHOLD ) << 16, nSamples ); /*Q10+Q16*/ + } +#else set16_fx( thresholdModificationNew, UNREACHABLE_THRESHOLD, nSamples ); /*Q10*/ +#endif k = GROUP_LENGTH / 2; move16(); @@ -869,6 +1164,36 @@ static void findCandidates( /* Modify thresholds for the following frame */ tmp_loop3 = add( k, 2 ); +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( EQ_16( element_mode, EVS_MONO ) ) + { + FOR( j = sub( k, 1 ); j < tmp_loop3; j++ ) + { + thresholdModificationNew[j] = BIG_THRESHOLD; /*Q10*/ + move16(); + + if ( GT_32( smoothedSpectrum[j], envelope[j] ) ) + { + thresholdModificationNew[j] = SMALL_THRESHOLD; /*Q10*/ + move16(); + } + } + } + ELSE + { + FOR( j = sub( k, 1 ); j < tmp_loop3; j++ ) + { + thresholdModificationNew32[j] = BIG_THRESHOLD << 16; /* 1.5f in Q10+Q16*/ + move32(); + + if ( GT_32( smoothedSpectrum[j], envelope[j] ) ) + { + thresholdModificationNew32[j] = 73819750; /* 1.1f in Q10+Q16*/ + move32(); + } + } + } +#else FOR( j = sub( k, 1 ); j < tmp_loop3; j++ ) { thresholdModificationNew[j] = BIG_THRESHOLD; /*Q10*/ @@ -880,6 +1205,7 @@ static void findCandidates( move16(); } } +#endif /* Jump to the next foot of the peak. */ k = upperIdx; move16(); @@ -897,12 +1223,15 @@ static void findTonalComponents_fx( Word16 *lowerIndex, /* OUT Q0*/ Word16 *upperIndex, /* OUT Q0*/ Word16 *numIndexes, /* OUT Q0*/ - Word16 nSamples, /* IN */ + Word16 nSamples, /* IN Q0*/ const Word32 *powerSpectrum, /* IN Q31-powerSpectrum_e*/ const Word16 powerSpectrum_e, - Word16 F0, /* IN */ + Word16 F0, /* IN Q10*/ Word16 *thresholdModification, /* IN Q10*/ - Word16 element_mode ) /* IN */ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 *thresholdModification32, /* IN Q10+Q16, unused in EVS_MONO */ +#endif + const Word16 element_mode ) /* IN, EVS_MONO or anything else */ { Word32 envelope[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/ Word32 smoothedSpectrum[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/ @@ -933,11 +1262,36 @@ static void findTonalComponents_fx( } ELSE { +#ifdef FIX_ISSUE_1966_F0_32BIT + /* Note: This is the key code for the issue 1966. With 32-bit thresholds, the comparison */ + /* powerSpectrum[k] > envelope[k]*thresholdModification[k] is closer to float and the */ + /* variable numIndexes becomes a bit higher compared to (rounded) 16-bit thresholds. */ + Word64 mult_64; + Word16 lshift; + Word16 mult_exp; + Word32 mult_32; + IF( element_mode == EVS_MONO ) + { + mult_64 = W_mult_32_16( envelope[k], thresholdModification[k] ); // (Q31-(powerSpectrum_e+LEVEL_EXP))+1+10 + lshift = W_norm( mult_64 ); + mult_32 = W_extract_h( W_shl( mult_64, lshift ) ); //(Q31-(powerSpectrum_e+LEVEL_EXP) + lshift )+11 -32 + mult_exp = sub( Q31, sub( add( sub( Q31, add( powerSpectrum_e, LEVEL_EXP ) ), add( 10, lshift ) ), 31 ) ); + } + ELSE + { + mult_64 = W_mult_32_32( envelope[k], thresholdModification32[k] ); // (Q31-(powerSpectrum_e+LEVEL_EXP))+1+10+16 + lshift = W_norm( mult_64 ); + mult_32 = W_extract_h( W_shl( mult_64, lshift ) ); //(Q31-(powerSpectrum_e+LEVEL_EXP) + lshift )+11 -32 + mult_exp = sub( Q31, sub( add( sub( Q31, add( powerSpectrum_e, LEVEL_EXP ) ), add( 10 + 16, lshift ) ), 31 ) ); + } + flag = BASOP_Util_Cmp_Mant32Exp( smoothedSpectrum[k], ( powerSpectrum_e + LEVEL_EXP ), mult_32, mult_exp ); +#else Word64 mult_64 = W_mult_32_16( envelope[k], thresholdModification[k] ); // (Q31-(powerSpectrum_e+LEVEL_EXP))+1+10 Word16 lshift = W_norm( mult_64 ); Word32 mult_32 = W_extract_h( W_shl( mult_64, lshift ) ); //(Q31-(powerSpectrum_e+LEVEL_EXP) + lshift )+11 -32 Word16 mult_exp = sub( Q31, sub( add( sub( Q31, add( powerSpectrum_e, LEVEL_EXP ) ), add( 10, lshift ) ), 31 ) ); flag = BASOP_Util_Cmp_Mant32Exp( smoothedSpectrum[k], ( powerSpectrum_e + LEVEL_EXP ), mult_32, mult_exp ); +#endif } /* There is 3 bits headroom in envelope and max of thresholdModification is 16384, so shifting left for 4 would produce overflow only when the result is anyhow close to 1 */ @@ -1073,11 +1427,22 @@ static void RefineThresholdsUsingPitch_fx( const Word32 lastPitchLag, /*Qx*/ const Word32 currentPitchLag, /*Qx*/ Word16 *pF0, /*Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 *pF0_32, /*Q10+Q16, NULL in EVS_MONO mode */ +#endif Word16 *thresholdModification /*Q10*/ +#ifdef FIX_ISSUE_1966_F0_32BIT + , + Word32 *thresholdModification32, /*Q10+Q16, NULL in EVS_MONO mode */ + const Word16 element_mode /*Q0 EVS_MONO or anything else */ +#endif ) { Word16 pitchIsStable; Word16 origF0; +#ifdef FIX_ISSUE_1966_F0_32BIT + Word32 origF0_32; /* unused in EVS_MONO mode */ +#endif Word32 L_tmp; /*pitchIsStable = (fabs(lastPitchLag-currentPitchLag) < 0.25f);*/ @@ -1092,14 +1457,42 @@ static void RefineThresholdsUsingPitch_fx( IF( pitchIsStable ) { - GetF0( nSamples, nSamplesCore, powerSpectrum, lastPitchLag, &origF0, pF0 ); +#ifdef FIX_ISSUE_1966_F0_32BIT + GetF0( nSamples, nSamplesCore, powerSpectrum, lastPitchLag, + &origF0, &origF0_32, pF0, pF0_32, element_mode ); + IF( EQ_16( element_mode, EVS_MONO ) ) + { + modifyThresholds( *pF0, 0, origF0, 0, + thresholdModification, thresholdModification32, element_mode ); + } + ELSE + { + modifyThresholds( 0, *pF0_32, 0, origF0_32, + thresholdModification, thresholdModification32, element_mode ); + } +#else + GetF0( nSamples, nSamplesCore, powerSpectrum, lastPitchLag, &origF0, pF0 ); modifyThresholds( *pF0, origF0, thresholdModification ); +#endif } ELSE { +#ifdef FIX_ISSUE_1966_F0_32BIT + IF( EQ_16( element_mode, EVS_MONO ) ) + { + *pF0 = 0; + move16(); + } + ELSE + { + *pF0_32 = 0; + move32(); + } +#else *pF0 = 0; move16(); +#endif } return; diff --git a/lib_dec/er_util_fx.c b/lib_dec/er_util_fx.c index 78fb12f10095dd70f6b23e325da6114d6ddc5248..888a0cd1c10b762263cabfd5d101789fb9e46b5d 100644 --- a/lib_dec/er_util_fx.c +++ b/lib_dec/er_util_fx.c @@ -10,7 +10,6 @@ #include #include "ivas_prot_fx.h" - /* static void setnoiseLevelMemory_fx() * * Helper function - updates buffer for minimumStatistics_fx function diff --git a/lib_dec/ivas_mdct_core_dec_fx.c b/lib_dec/ivas_mdct_core_dec_fx.c old mode 100644 new mode 100755 index 61c4bf0ce36a45451877ca5986aecc1d7a65a5db..397a0728e7ae467c14779c66e870ac38a291c257 --- a/lib_dec/ivas_mdct_core_dec_fx.c +++ b/lib_dec/ivas_mdct_core_dec_fx.c @@ -40,7 +40,6 @@ #include "basop_proto_func.h" #include "ivas_prot_fx.h" - /*-----------------------------------------------------------------* * Function mdct_read_IGF_bits() * diff --git a/lib_dec/tonalMDCTconcealment_fx.c b/lib_dec/tonalMDCTconcealment_fx.c index e45aac27c19905187e937acac0b44d947e6358e4..ae55088c0abb5669f97d89814f7c0e6ef018dae8 100644 --- a/lib_dec/tonalMDCTconcealment_fx.c +++ b/lib_dec/tonalMDCTconcealment_fx.c @@ -23,7 +23,11 @@ static void CalcMDXT( const TonalMDCTConcealPtr hTonalMDCTConc, const Word16 typ static void CalcPowerSpec( const Word32 *mdctSpec, const Word16 mdctSpec_exp, const Word32 *mdstSpec, const Word16 mdstSpec_exp, const Word16 nSamples, const Word16 floorPowerSpectrum, Word32 *powerSpec, Word16 *powerSpec_exp ); static void CalcPowerSpecAndDetectTonalComponents_fx( TonalMDCTConcealPtr const hTonalMDCTConc, Word32 secondLastMDST[], Word16 secondLastMDST_exp, Word32 secondLastMDCT[], Word16 secondLastMDCT_exp, Word32 const pitchLag, const PsychoacousticParameters *psychParamsCurrent, Word16 element_mode ); static void FindPhases( TonalMDCTConcealPtr const hTonalMDCTConc, Word32 secondLastMDCT[], Word32 secondLastMDST[], Word16 diff_exp ); +#ifdef FIX_ISSUE_1966_PHASE_DIFF +static void FindPhaseDifferences( TonalMDCTConcealPtr const hTonalMDCTConc, Word32 powerSpectrum[], const Word16 element_mode ); +#else static void FindPhaseDifferences( TonalMDCTConcealPtr const hTonalMDCTConc, Word32 powerSpectrum[] ); +#endif /*******************************************************/ @@ -598,7 +602,12 @@ static void FindPhases( /* o: Phase difference [-pi;pi] 2Q13*/ static void FindPhaseDifferences( TonalMDCTConcealPtr const hTonalMDCTConc, /* i : Pointer to internal structure */ - Word32 powerSpectrum[] ) /* i : Power spectrum data Qx */ + Word32 powerSpectrum[] /* i : Power spectrum data Qx */ +#ifdef FIX_ISSUE_1966_PHASE_DIFF + , + const Word16 element_mode /* i : EVS_MONO or anything else */ +#endif +) { Word16 i, k; Word16 *phaseDiff; @@ -627,11 +636,45 @@ static void FindPhaseDifferences( { phaseDiff[i] = 0; /*(float)tan(0.0f*EVS_PI/bandwidth);*/ move16(); + +#ifdef FIX_ISSUE_1966_PHASE_DIFF + /* Note: This version is closer to the float reference, except */ + /* for the phase range. It is here [-2PI..+2PI[, while */ + /* in float it is [0..4PI[. */ + IF( EQ_16( element_mode, EVS_MONO ) ) + { + if ( s_and( k, 1 ) != 0 ) + { + phaseDiff[i] = -12868 /*-EVS_PI 3Q12*/; + move16(); + } + } + ELSE + { + if ( EQ_16( s_and( k, 3 ), 1 ) ) + { + phaseDiff[i] = 12868 /* 1*EVS_PI 3Q12*/; + move16(); + } + if ( EQ_16( s_and( k, 3 ), 2 ) ) + { + phaseDiff[i] = -25736 /*-2*EVS_PI 3Q12*/; + move16(); + } + if ( EQ_16( s_and( k, 3 ), 3 ) ) + { + phaseDiff[i] = -12868 /*-1*EVS_PI 3Q12*/; + move16(); + } + } +#else if ( s_and( k, 1 ) != 0 ) { phaseDiff[i] = -12868 /*-EVS_PI 3Q12*/; move16(); } + +#endif } ELSE { @@ -639,11 +682,41 @@ static void FindPhaseDifferences( { phaseDiff[i] = 12868 /*EVS_PI 3Q12*/; /*(float)tan(2.0f*PI/bandwidth);*/ move16(); + +#ifdef FIX_ISSUE_1966_PHASE_DIFF + IF( EQ_16( element_mode, EVS_MONO ) ) + { + if ( s_and( k, 1 ) != 0 ) + { + phaseDiff[i] = 0 /*0 Q13*/; /*2Q13*/ + move16(); + } + } + ELSE + { + if ( EQ_16( s_and( k, 3 ), 1 ) ) + { + phaseDiff[i] = -25736 /*-2*EVS_PI 3Q12*/; + move16(); + } + if ( EQ_16( s_and( k, 3 ), 2 ) ) + { + phaseDiff[i] = -12868 /*-1*EVS_PI 3Q12*/; + move16(); + } + if ( EQ_16( s_and( k, 3 ), 3 ) ) + { + phaseDiff[i] = 0 /* 0*EVS_PI 3Q12*/; + move16(); + } + } +#else if ( s_and( k, 1 ) != 0 ) { phaseDiff[i] = 0 /*0 Q13*/; /*2Q13*/ move16(); } +#endif } ELSE { @@ -793,10 +866,13 @@ static void CalcPowerSpecAndDetectTonalComponents_fx( nSamples, hTonalMDCTConc->nSamplesCore, floorPowerSpectrum, psychParamsCurrent, element_mode ); - FindPhases( hTonalMDCTConc, secondLastMDCT, secondLastMDST, sub( secondLastMDST_exp, secondLastMDCT_exp ) ); +#ifdef FIX_ISSUE_1966_PHASE_DIFF + FindPhaseDifferences( hTonalMDCTConc, powerSpectrum, element_mode ); +#else FindPhaseDifferences( hTonalMDCTConc, powerSpectrum ); +#endif IF( hTonalMDCTConc->pTCI->numIndexes > 0 ) { @@ -944,8 +1020,8 @@ void TonalMDCTConceal_Detect_fx( Word16 i, powerSpectrum_exp, secondLastMDST_exp, s; Word16 nSamples; Word32 sns_int_scf_fx[FDNS_NPTS]; - set32_fx( sns_int_scf_fx, 0, FDNS_NPTS ); + set32_fx( sns_int_scf_fx, 0, FDNS_NPTS ); nSamples = hTonalMDCTConc->nSamples; move16();