/* * Copyright (c) 2011-2019 Belledonne Communications SARL. * * This file is part of bcg729. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "typedef.h" #include "codecParameters.h" #include "basicOperationsMacros.h" #include "utils.h" #include #include "fixedCodebookSearch.h" /*** local functions ***/ void computeImpulseResponseCorrelationMatrix(word16_t impulseResponse[], word16_t correlationSignal[], int correlationSignalSign[], word32_t Phi[L_SUBFRAME][L_SUBFRAME]); void computePhiDiagonal(int j, word16_t impulseResponse[], word32_t Phi[L_SUBFRAME][L_SUBFRAME], uint16_t PhiScaling); /*****************************************************************************/ /* fixedCodebookSearch: compute fixed codebook parameters (codeword and sign)*/ /* compute also fixed codebook vector as in spec 3.8.1 */ /* parameters: */ /* -(i) targetSignal: 40 values as in spec A.3.6 in Q0 */ /* -(i) impulseResponse: 40 values as in spec A.3.5 in Q12 */ /* -(i) intPitchDelay: current integer pitch delay */ /* -(i) lastQuantizedAdaptativeCodebookGain: previous subframe pitch */ /* gain quantized in Q14 */ /* -(i) filteredAdaptativeCodebookVector : 40 values in Q0 */ /* -(i) adaptativeCodebookGain : in Q14 */ /* -(o) fixedCodebookParameter */ /* -(o) fixedCodebookPulsesSigns */ /* -(o) fixedCodebookVector : 40 values as in spec 3.8, eq45 in Q13 */ /* -(o) fixedCodebookVectorConvolved : 40 values as in spec 3.9, eq64 */ /* in Q12. */ /* */ /*****************************************************************************/ void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], int16_t intPitchDelay, word16_t lastQuantizedAdaptativeCodebookGain, word16_t filteredAdaptativeCodebookVector[], word16_t adaptativeCodebookGain, uint16_t *fixedCodebookParameter, uint16_t *fixedCodebookPulsesSigns, word16_t fixedCodebookVector[], word16_t fixedCodebookVectorConvolved[]) { int i,j,n; word16_t fixedCodebookTargetSignal[L_SUBFRAME]; word32_t correlationSignal32[L_SUBFRAME]; /* on 32 bits in Q12 */ word16_t correlationSignal[L_SUBFRAME]; /* normalised to fit on 13 bits */ word32_t correlationSignalMax = 0; word32_t abscCrrelationSignal32; uint16_t correlationSignalMaxNorm; int correlationSignalSign[L_SUBFRAME]; /* to store the sign of each correlationSignal element */ /* build the matrix Ф' : impulseResponse correlation matrix spec 3.8.1 eq51, eq56 and eq57 */ /* correlationSignal turns to absolute values and sign of elements is stored in correlationSignalSign */ word32_t Phi[L_SUBFRAME][L_SUBFRAME] = {{0}}; int m3Base; int i0=0, i1=0, i2=0, i3=0; word32_t correlationSquareMax = -1; word32_t energyMax = 1; int m0=0, m1=0, m2=0, m3=0; int mSwitch[2][4] = {{2,3,0,1},{3,0,1,2}}; int mIndex; int jx = 0; /* compute the target signal for fixed codebook spec 3.8.1 eq50 : fixedCodebookTargetSignal[i] = targetSignal[i] - (adaptativeCodebookGain * filteredAdaptativeCodebookVector[i]) */ for (i=0; i=0?correlationSignal32[n]:-correlationSignal32[n]; if (abscCrrelationSignal32>correlationSignalMax) { correlationSignalMax = abscCrrelationSignal32; } } /* normalise on 13 bits */ correlationSignalMaxNorm = countLeadingZeros(correlationSignalMax); if (correlationSignalMaxNorm<18) { /* if it doesn't already fit on 13 bits */ for (i=0; i select m2 */ if (correlationSignal[j]>correlationM2 && j!=firstM2) { currentM2 = j; correlationM2=correlationSignal[j]; } } firstM2 = currentM2; /* to avoid selecting the same maximum at next iteration */ energyM2 = Phi[currentM2][currentM2]; /* compute the energy with terms of eq55 using m2 only: Phi'(m2,m2) */ /* with selected m2, test the 8 m3 possibilities for the current m3 track */ for (j=mSwitch[mIndex][1]; j C^2/E > C^2max/Emax => Emax*C^2 > C^2max*E */ if (MULT32_32(m3TrackEnergy,correlationM2M3Square) > MULT32_32(energyM2M3, m3TrackCorrelationSquare)) { m3TrackCorrelationSquare = correlationM2M3Square; m3TrackEnergy = energyM2M3; correlationM2M3Max = correlationM2M3; m3 = j; m2 = currentM2; } } } energyM2M3Max = m3TrackEnergy; /* reset the current m3 track correlationSquare and energy */ m3TrackCorrelationSquare = -1; m3TrackEnergy = 1; for (i=mSwitch[mIndex][2]; i C^2/E > C^2max/Emax => Emax*C^2 > C^2max*E */ if (MULT32_32(m3TrackEnergy,correlationM2M3M0M1Square) > MULT32_32(energyM2M3M0M1, m3TrackCorrelationSquare)) { m3TrackCorrelationSquare = correlationM2M3M0M1Square; m3TrackEnergy = energyM2M3M0M1; m1 = j; m0 = i; } } } /* check with currently selected indexes if this one is better */ if (MULT32_32(energyMax,m3TrackCorrelationSquare) > MULT32_32(m3TrackEnergy, correlationSquareMax)) { correlationSquareMax = m3TrackCorrelationSquare; energyMax = m3TrackEnergy; if (mIndex==0) { i0 = m0; i1 = m1; i2 = m2; i3 = m3; } else { i0 = m3; i1 = m0; i2 = m1; i3 = m2; } jx = m3Base - 3; /* needed for parameter computation apec 3.8.2 eq62 */ } } mSwitch[0][1]++; mSwitch[1][0]++; /*increment the m3Base into the mSwitch */ } /* compute the fixedCodebookVector */ for (i=0; i>1) | /* as in spec 3.8.2 eq61 */ (uint16_t)(((correlationSignalSign[i1]+1)>>1)<<1) | (uint16_t)(((correlationSignalSign[i2]+1)>>1)<<2) | (uint16_t)(((correlationSignalSign[i3]+1)>>1)<<3); /* compute the fixedCodebook vector convolved with impulse response spec 3.9 eq64 */ /* this vector is used in gain quantization but computed here because it's faster doing it having directly the impulses positions */ /* eq64 make use of fixedCodebook vector adapted by eq48, using the impulse position(and thus fixed codebook vector before the adaptation) but */ /* the impulse response adapted as in eq49 gives the same output */ /* reset the vector */ for (i=0; i 0) { for(i=i0, j=0; i 0) { for(i=i1, j=0; i 0) { for(i=i2, j=0; i 0) { for(i=i3, j=0; i acc in Q24 */ Phi[iComp][iComp] = SHR(acc,1); /* divide by 2: eq57*/ } /* check for possible overflow: Phi will be summed 10 times, so max Phi (by construction Phi[0][0]*2 is the max of Phi-> 2*Phi[0][0]*10 must be < 0x7fff ffff -> Phi[0][0]< 0x06666666 - otherwise scale Phi)*/ if (Phi[0][0]>0x6666666) { PhiScaling = 3 - countLeadingZeros((Phi[0][0]<<1) + 0x3333333); /* complement 0xccccccc adding 0x3333333 to shift by one when max(2*Phi[0][0]) is in 0x0fffffff < max < 0xcccccc */ for (i=0; i absolute value and get sign (and his inverse in an array) */ for (i=0; i= 0) { correlationSignalSign[i] = 1; correlationSignalSignInv[i] = -1; } else { /* correlationSignal < 0 */ correlationSignalSign[i] = -1; correlationSignalSignInv[i] = 1; correlationSignal[i] = -correlationSignal[i]; } } /* modify the signs according to eq56 */ for (i=0; i0) { /* is sign(correlationSignal[i]) is positive, use the correlationSignalSign otherwise the inverted one */ signOfCorrelationSignalJ = correlationSignalSign; } else { signOfCorrelationSignalJ = correlationSignalSignInv; } for (j=0; j<=i; j++) { /* multiply by the selected sign the matrix element */ /* Note : even the not needed and thus not computed elements are multiplicated... might found other way to do this sign stuff to be more efficient */ Phi[i][j] = Phi[i][j] * signOfCorrelationSignalJ[j]; } } /* duplicate the usefull values to their symetric part to get easier acces to the matrix elements */ for (i=0; i<8; i++) { for (j=0; j<4; j++) { int k; int startIndex = 5*i+j; for(k=0; k<=startIndex; k++) { Phi[startIndex-k][L_SUBFRAME-1-k] = Phi[L_SUBFRAME-1-k][startIndex-k]; } } } return; } /* compute a diagonal of Phi values: start from Phi(39,j) and step Phi(38, j-1) down to Phi(39-j, 0) */ /* Phi(i,j) = Phi(i+1,j+1) + h(39-i)*h(39-j) */ void computePhiDiagonal(int j, word16_t impulseResponse[], word32_t Phi[L_SUBFRAME][L_SUBFRAME], uint16_t PhiScaling) { word32_t acc = 0; int i=L_SUBFRAME -1; int iComp = 0; int jComp = L_SUBFRAME - 1 - j; if (PhiScaling == 0) { for (; j>=0; j--, i--, jComp++, iComp++) { acc = MAC16_16(acc, impulseResponse[iComp], impulseResponse[jComp]); Phi[i][j] = acc; } } else { for (; j>=0; j--, i--, jComp++, iComp++) { acc = MAC16_16(acc, impulseResponse[iComp], impulseResponse[jComp]); Phi[i][j] = SHR(acc,PhiScaling); } } }