/* LSPQuantization.c Copyright (C) 2011 Belledonne Communications, Grenoble, France Author : Johan Pascal 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "typedef.h" #include "codecParameters.h" #include "basicOperationsMacros.h" #include "g729FixedPointMath.h" #include "codebooks.h" #include "LSPQuantization.h" #include "string.h" /* static buffers */ word16_t previousqLSFInit[NB_LSP_COEFF] = {2339, 4679, 7018, 9358, 11698, 14037, 16377, 18717, 21056, 23396}; /* PI*(float)(j+1)/(float)(M+1) */ /* initialise the stactic buffers */ void initLSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext) { int i; for (i=0; ipreviousqLSF[i], previousqLSFInit, NB_LSP_COEFF*sizeof(word16_t)); } return; } /**********************************************************************************/ /* noiseLSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */ /* qLSF->qLSP as described in spec A3.2.4 */ /* parameters: */ /* -(i/o) previousqLSF : 4 previousqLSF, is updated by this function */ /* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */ /* -(o) qLSPCoefficients : 10 qLSP coefficients in Q15 */ /* -(o) parameters : 3 parameters L0, L1, L2 */ /* */ /**********************************************************************************/ void noiseLSPQuantization(word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF], word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint8_t parameters[]) { int i,j; int L0; word16_t LSF[NB_LSP_COEFF]; /* LSF coefficients in Q2.13 range [0, Pi[ */ word16_t weights[NB_LSP_COEFF]; /* weights in Q11 */ word16_t weightsThreshold[NB_LSP_COEFF]; /* store in Q13 the threshold used to compute the weights */ word16_t L1index[L0_RANGE]; word16_t L2index[L0_RANGE]; word32_t weightedMeanSquareError[L0_RANGE]; word16_t quantizerOutput[NB_LSP_COEFF]; word16_t qLSF[NB_LSP_COEFF]; /*** compute LSF in Q2.13 : lsf = arcos(lsp) range [0, Pi[ spec 3.2.4 eq18 ***/ for (i=0; i0) { weights[i] = ONE_IN_Q11; } else { weights[i] = (word16_t)SATURATE(ADD32(PSHR(MULT16_16(MULT16_16_Q13(weightsThreshold[i], weightsThreshold[i]), 10), 2), ONE_IN_Q11), MAXINT16); } } weights[4] = MULT16_16_Q14(weights[4], ONE_POINT_2_IN_Q14); weights[5] = MULT16_16_Q14(weights[5], ONE_POINT_2_IN_Q14); /*** compute the coefficients for the two noise noise MA Predictors ***/ for (L0=0; L0 acc in Q2.28 */ } targetVector[i] = MULT16_16_Q12((word16_t)PSHR(acc, 15), invNoiseMAPredictorSum[L0][i]); /* acc->Q13 and invMAPredictorSum in Q12 -> targetVector in Q13 */ } /* find closest match for predictionError (minimize mean square diff) in L1 subset codebook: 32 entries from L1 codebook */ for (i=0; i l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */ /* works on the first five coefficients only */ meanSquareDiff = MAXINT32; for (i=0; i result in Q13 */ acc = MAC16_16(acc, difftargetVectorL1L2, MULT16_16_Q11(difftargetVectorL1L2, weights[j])); /* weights in Q11, diff in Q13 */ } for (j=NB_LSP_COEFF/2; j result in Q13 */ acc = MAC16_16(acc, difftargetVectorL1L3, MULT16_16_Q11(difftargetVectorL1L3, weights[j])); /* weights in Q11, diff in Q13 */ } if (accSUB16(quantizedVector[i],GAP1)) { quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); } } for (i=NB_LSP_COEFF/2+1; iSUB16(quantizedVector[i],GAP1)) { quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); } } /* rearrange the whole quantizedVector with a distance of 0.0006 */ for (i=1; iSUB16(quantizedVector[i],GAP2)) { quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1); quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1); } } /* compute the weighted mean square distance using the final quantized vector according to eq21 */ weightedMeanSquareError[L0]=0; for (i=0; i result in Q13 */ weightedMeanSquareError[L0] = MAC16_16(weightedMeanSquareError[L0], difftargetVectorQuantizedVector, MULT16_16_Q11(difftargetVectorQuantizedVector, weights[i])); /* weights in Q11, diff in Q13 */ } } /* now select L0 and copy the selected coefficients to the output buffer */ if (weightedMeanSquareError[0] Q28 */ for (j=0; j0; i--) { memcpy(previousqLSF[i], previousqLSF[i-1], NB_LSP_COEFF*sizeof(word16_t)); } memcpy(previousqLSF[0], quantizerOutput, NB_LSP_COEFF*sizeof(word16_t)); /*** qLSF stability check ***/ insertionSort(qLSF, NB_LSP_COEFF); /* check for low limit on qLSF[0] */ if (qLSF[1]qLSF_MAX) { qLSF[NB_LSP_COEFF-1] = qLSF_MAX; } /* convert qLSF to qLSP: qLSP = cos(qLSF) */ for (i=0; iqLSP as described in spec A3.2.4 */ /* parameters: */ /* -(i/o) encoderChannelContext : the channel context data */ /* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */ /* -(o) qLSPCoefficients : 10 qLSP coefficients in Q15 */ /* -(o) parameters : 4 parameters L0, L1, L2, L3 */ /* */ /*****************************************************************************/ void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint16_t parameters[]) { int i,j; word16_t LSF[NB_LSP_COEFF]; /* LSF coefficients in Q2.13 range [0, Pi[ */ word16_t weights[NB_LSP_COEFF]; /* weights in Q11 */ word16_t weightsThreshold[NB_LSP_COEFF]; /* store in Q13 the threshold used to compute the weights */ int L0; word32_t weightedMeanSquareError[L0_RANGE]; word16_t L1index[L0_RANGE]; word16_t L2index[L0_RANGE]; word16_t L3index[L0_RANGE]; word16_t quantizerOutput[NB_LSP_COEFF]; word16_t qLSF[NB_LSP_COEFF]; /*** compute LSF in Q2.13 : lsf = arcos(lsp) range [0, Pi[ spec 3.2.4 eq18 ***/ for (i=0; i0) { weights[i] = ONE_IN_Q11; } else { weights[i] = (word16_t)SATURATE(ADD32(PSHR(MULT16_16(MULT16_16_Q13(weightsThreshold[i], weightsThreshold[i]), 10), 2), ONE_IN_Q11), MAXINT16); } } weights[4] = MULT16_16_Q14(weights[4], ONE_POINT_2_IN_Q14); weights[5] = MULT16_16_Q14(weights[5], ONE_POINT_2_IN_Q14); /*** compute the coefficients for the two MA Predictors ***/ for (L0=0; L0previousqLSF[j][i], MAPredictor[L0][j][i]); /* previousqLSF in Q2.13 and MAPredictor in Q0.15-> acc in Q2.28 */ } targetVector[i] = MULT16_16_Q12((word16_t)PSHR(acc, 15), invMAPredictorSum[L0][i]); /* acc->Q13 and invMAPredictorSum in Q12 -> targetVector in Q13 */ } /* find closest match for predictionError (minimize mean square diff) in L1 codebook */ for (i=0; i l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */ /* works on the first five coefficients only */ meanSquareDiff = MAXINT32; for (i=0; i result in Q13 */ word16_t difftargetVectorL1L2 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */ acc = MAC16_16(acc, difftargetVectorL1L2, MULT16_16_Q11(difftargetVectorL1L2, weights[j])); /* weights in Q11, diff in Q13 */ } if (acc l[i] - l^[i] = (wi - w^[i])/(1-SumMAPred[i]) but ITU code ignores this denominator */ /* works on the first five coefficients only */ meanSquareDiff = MAXINT32; for (i=0; i result in Q13 */ word16_t difftargetVectorL1L3 = SATURATE(MULT16_16_Q15(SUB32(SUB32(targetVector[j], L1[L1index[L0]][j]), L2L3[i][j]), MAPredictorSum[L0][j]), MAXINT16); /* targetVector, L1 and L2L3 in Q13 -> result in Q13 */ acc = MAC16_16(acc, difftargetVectorL1L3, MULT16_16_Q11(difftargetVectorL1L3, weights[j])); /* weights in Q11, diff in Q13 */ } if (accSUB16(quantizedVector[i],GAP1)) { quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); } } for (i=NB_LSP_COEFF/2+1; iSUB16(quantizedVector[i],GAP1)) { quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP1), 1); } } /* rearrange the whole quantizedVector with a distance of 0.0006 */ for (i=1; iSUB16(quantizedVector[i],GAP2)) { quantizedVector[i-1] = PSHR(SUB16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1); quantizedVector[i] = PSHR(ADD16(ADD16(quantizedVector[i], quantizedVector[i-1]), GAP2), 1); } } /* compute the weighted mean square distance using the final quantized vector according to eq21 */ weightedMeanSquareError[L0]=0; for (i=0; i result in Q13 */ weightedMeanSquareError[L0] = MAC16_16(weightedMeanSquareError[L0], difftargetVectorQuantizedVector, MULT16_16_Q11(difftargetVectorQuantizedVector, weights[i])); /* weights in Q11, diff in Q13 */ } } /* now select L0 and copy the selected coefficients to the output buffer */ if (weightedMeanSquareError[0] Q28 */ for (j=0; jpreviousqLSF[j][i]); } /* acc in Q2.28, shift back the acc to a Q2.13 with rounding */ qLSF[i] = (word16_t)PSHR(acc, 15); /* qLSF in Q2.13 */ } /* update the previousqLSF buffer with current quantizer output */ for (i=MA_MAX_K-1; i>0; i--) { memcpy(encoderChannelContext->previousqLSF[i], encoderChannelContext->previousqLSF[i-1], NB_LSP_COEFF*sizeof(word16_t)); } memcpy(encoderChannelContext->previousqLSF[0], quantizerOutput, NB_LSP_COEFF*sizeof(word16_t)); /*** qLSF stability check ***/ insertionSort(qLSF, NB_LSP_COEFF); /* check for low limit on qLSF[0] */ if (qLSF[1]qLSF_MAX) { qLSF[NB_LSP_COEFF-1] = qLSF_MAX; } /* convert qLSF to qLSP: qLSP = cos(qLSF) */ for (i=0; i