/*==================================================================================== EVS Codec 3GPP TS26.443 Jun 30, 2015. Version CR 26.443-0006 ====================================================================================*/ #include "cnst.h" #include "rom_enc.h" #include "stl.h" #include "basop_util.h" #include #include #include "prot.h" #include "rom_com.h" /*-------------------------------------------------------------------* * EncodeIndex() * * *-------------------------------------------------------------------*/ int EncodeIndex( int Bandwidth, int PeriodicityIndex, Encoder_State *st ) { if (PeriodicityIndex & kLtpHmFlag) { int LtpPitchIndex = PeriodicityIndex >> 9; assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); --PeriodicityIndex; assert((PeriodicityIndex & 0xff) < (1 << NumRatioBits[Bandwidth][LtpPitchIndex])); push_next_indice(st, PeriodicityIndex & 0xff, NumRatioBits[Bandwidth][LtpPitchIndex]); return NumRatioBits[Bandwidth][LtpPitchIndex]; } else { push_next_indice(st, PeriodicityIndex, 8); return 8; } } /*-------------------------------------------------------------------* * GetWeight() * * *-------------------------------------------------------------------*/ static float GetWeight(int i) { i = 3 * i - 2; return (float)(pow(i, 0.3) / pow(256 - 1, 0.3)); } /*-------------------------------------------------------------------* * SearchPeriodicityIndex_Single() * * *-------------------------------------------------------------------*/ static float SearchPeriodicityIndex_Single( const float AbsMdct3[], int NumToConsider, int Lag, int FractionalResolution ) { int HighestMultiplier; float AbsMeanCurrent3; /* Mean for BucketWidth == 3 */ int Limit; int OldIndex, i; Limit = (NumToConsider - 1) << FractionalResolution; AbsMeanCurrent3 = 0; HighestMultiplier = 1; for (i=Lag; i> FractionalResolution; AbsMeanCurrent3 += AbsMdct3[OldIndex] * GetWeight(HighestMultiplier); ++HighestMultiplier; } return AbsMeanCurrent3 / (HighestMultiplier - 1 + 0.00001f); } /*-------------------------------------------------------------------* * SearchPeriodicityIndex_Range() * * *-------------------------------------------------------------------*/ static void SearchPeriodicityIndex_Range( const float AbsMdct3[], int NumToConsider, int Lo, int Hi, int FractionalResolution, int Adj, int Spacing, int *PeriodicityIndex, float *Score ) { int Index, BestIndex; float CurrentScore, BestScore; int B; BestScore = -1e30f; BestIndex = 0; for (Index = Lo; Index < Hi; Index += Spacing) { CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Index + Adj, FractionalResolution ); if (CurrentScore > BestScore) { BestScore = CurrentScore; BestIndex = Index; } } if (BestScore > *Score) { *Score = BestScore; *PeriodicityIndex = BestIndex; } B = BestIndex - (Spacing >> 1); B = max(Lo, B); for (Index = B; Index < BestIndex; ++Index) { CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Index + Adj, FractionalResolution ); if (CurrentScore > *Score) { *Score = CurrentScore; *PeriodicityIndex = Index; } } B = BestIndex + (Spacing >> 1); for (Index = BestIndex + 1; Index <= B; ++Index) { CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Index + Adj, FractionalResolution ); if (CurrentScore > *Score) { *Score = CurrentScore; *PeriodicityIndex = Index; } } return; } /*-------------------------------------------------------------------* * UnmapIndex() * * *-------------------------------------------------------------------*/ /* Returns: PeriodicityIndex */ int SearchPeriodicityIndex( const float Mdct[], /* (I) Coefficients, Mdct[0..NumCoeffs-1] */ const float UnfilteredMdct[], /* (I) Unfiltered coefficients, UnfilteredMdct[0..NumCoeffs-1] */ int NumCoeffs, /* (I) Number of coefficients */ int TargetBits, /* (I) Target bit budget (excl. Done flag) */ short LtpPitchLag, float LtpGain, /* (I) LTP gain */ float *RelativeScore /* (O) Energy concentration factor */ ) { float AbsMdct3[MAX_LENGTH], A, B, C=0.f; int i; int MaxAt; float Score; int PeriodicityIndex = 0; int NumToConsider = NumCoeffs; float AbsTotal; Score = -1e30f; A = (float)fabs(Mdct[0]); B = (float)fabs(Mdct[1]); for (i = 1; i < NumToConsider - 3; i += 3) { C = (float)fabs(Mdct[i + 1]); AbsMdct3[i] = A + B + C; A = (float)fabs(Mdct[i + 2]); AbsMdct3[i + 1] = A + B + C; B = (float)fabs(Mdct[i + 3]); AbsMdct3[i + 2] = A + B + C; } if (i < NumToConsider - 1) { C = (float)fabs(Mdct[i + 1]); AbsMdct3[i] = A + B + C; } if (i + 1 < NumToConsider - 1) { A = (float)fabs(Mdct[i + 2]); AbsMdct3[i + 1] = A + B + C; } AbsTotal = 0.0f; if (UnfilteredMdct != NULL) { for (i = 0; i < NumToConsider; ++i) { AbsTotal += (float)fabs(UnfilteredMdct[i]); } } else { for (i = 1; i < NumToConsider - 1; i += 3) { AbsTotal += AbsMdct3[i]; } } if ((LtpPitchLag > 0) && (LtpGain > kLtpHmGainThr)) { int FractionalResolution = kLtpHmFractionalResolution; int Multiplier; int LtpPitchIndex; int Bandwidth; Bandwidth = NumCoeffs >= 256; LtpPitchIndex = ((LtpPitchLag + (1 << (kLtpHmFractionalResolution - 1))) >> kLtpHmFractionalResolution) - 2; assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16); for (Multiplier = 1; Multiplier <= (1 << NumRatioBits[Bandwidth][LtpPitchIndex]); ++Multiplier) { float CurrentScore; int Lag; Lag = (LtpPitchLag * (int)(4 * Ratios[Bandwidth][LtpPitchIndex][Multiplier-1])) >> 2; if (Lag >= (4 << FractionalResolution) && (Lag <= ((NumToConsider-2) << FractionalResolution))) { CurrentScore = SearchPeriodicityIndex_Single( AbsMdct3, NumToConsider, Lag, FractionalResolution ); if (CurrentScore > Score) { Score = CurrentScore; PeriodicityIndex = Multiplier | kLtpHmFlag; } } } PeriodicityIndex |= LtpPitchIndex << 9; } else { if (UnfilteredMdct != NULL) { MaxAt = 1; A = AbsMdct3[1]; for (i = 4; i < NumToConsider - 1; i += 3) { if (AbsMdct3[i] > AbsMdct3[MaxAt]) { MaxAt = i; } A += AbsMdct3[i]; } if (AbsMdct3[MaxAt] > A * 0.7f) { NumToConsider = min(NumToConsider, MaxAt + 4); } } SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 0, 16, 3, GET_ADJ2(0, 6, 3), 4, &PeriodicityIndex, &Score ); SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 16, 80, 4, GET_ADJ2(16, 8, 4), 4, &PeriodicityIndex, &Score ); SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 80, 208, 3, GET_ADJ2(80, 12, 3), 4, &PeriodicityIndex, &Score ); if (NumToConsider <= 128) { /* no long lags for band-limited MDCTs */ SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 208, 88 + NumToConsider, 0, GET_ADJ2(224, 188, 0), 1, &PeriodicityIndex, &Score ); } else { if (TargetBits > kSmallerLagsTargetBitsThreshold && NumCoeffs >= 256) { SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 208, 224, 1, GET_ADJ2(208, 28, 1), 1, &PeriodicityIndex, &Score ); SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 224, 256, 0, GET_ADJ2(224, 188, 0 ), 1, &PeriodicityIndex, &Score ); } else { SearchPeriodicityIndex_Range( AbsMdct3, NumToConsider, 208, 256, 1, GET_ADJ2(208, 28, 1), 1, &PeriodicityIndex, &Score ); } } } if (AbsTotal > 0) { *RelativeScore = Score/AbsTotal*(float)NumCoeffs; } else { *RelativeScore = 0; } return PeriodicityIndex; } /*-------------------------------------------------------------------* * PeakFilter() * * *-------------------------------------------------------------------*/ #define kPeakElevationThreshold 1.0f static void PeakFilter( const float x[], /* (I) absolute spectrum */ float y[], /* (O) filtered absolute spectrum, must not alias x[] */ int L_frame /* (I) number of spectral lines */ ) { int flen, i; float a, m; flen = (L_frame >> 4); m = kPeakElevationThreshold / (float)(2*flen + 1); a = 0.0f; for (i=0; i= 256, LtpPitchLag, (targetBits - *hm_bits <= kSmallerLagsTargetBitsThreshold) || (L_frame < 256), &fract_res, &lag ); /* Render harmonic model */ tcx_hm_render( lag, fract_res, LtpGain, p ); /* Calculate and quantize gain */ gain = 0; tcx_hm_quantize_gain( abs_spectrum, env, lag, fract_res, p, L_frame, coder_type, RelativeScore, &prm_hm[2], &gain ); /* Decision */ if (gain > 0) { prm_hm[0] = 1; /* flag: on */ *hm_bits += CountIndexBits( L_frame >= 256, prm_hm[1] ); if (coder_type == VOICED) { *hm_bits += kTcxHmNumGainBits; } tcx_hm_modify_envelope( gain, lag, fract_res, p, env, L_frame ); } else { prm_hm[0] = 0; /* flag: off */ prm_hm[1] = -1; /* pitch index */ prm_hm[2] = 0; /* gain index */ } return; }