/*
* 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 "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