/* * 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 "basicOperationsMacros.h" #include "codecParameters.h" #include "g729FixedPointMath.h" #include "codebooks.h" /*****************************************************************************/ /* insertionSort : sort an array in growing order using insertion algorithm */ /* parameters : */ /* -(i/o) x: the array to be sorted */ /* -(i) length: the array length */ /* */ /*****************************************************************************/ void insertionSort(word16_t x[], int length) { int i, j; word16_t currentValue; for (i=1; i=0) && (x[j]>currentValue)) { x[j+1] = x[j]; j--; } x[j+1] = currentValue; } return; } /*****************************************************************************/ /* getMinInArray : get the minimum value from an array */ /* parameters : */ /* -(i) x: the array to be searched */ /* -(i) length: the array length */ /* returns : the minimum value found in the array */ /* */ /*****************************************************************************/ word16_t getMinInArray(word16_t x[], int length) { word16_t min = MAXINT16; int i; for (i=0; i 0) { qLSP[i-1] = SUB16(qLSP[i-1], delta); /* qLSP still in Q2.13 */ qLSP[i] = ADD16(qLSP[i], delta); } } return; } /*****************************************************************************/ /* synthesisFilter : compute 1/[A(z)] using the following algorithm */ /* filteredSignal[n] = inputSignal[n] */ /* - Sum(i=1..10)filterCoefficients[i]*filteredSignal[n-i] */ /* for n in [0, L_SUBFRAME[ */ /* parameters: */ /* -(i) inputSignal: 40 values in Q0 */ /* -(i) filterCoefficients: 10 coefficients in Q12 */ /* -(i/o) filteredSignal: 50 values in Q0 accessed in ranges [-10,-1] */ /* as input and [0, 39] as output. */ /* */ /*****************************************************************************/ void synthesisFilter(word16_t inputSignal[], word16_t filterCoefficients[], word16_t filteredSignal[]) { int i; for (i=0; i acc in Q12 */ } filteredSignal[i] = (word16_t)SATURATE(PSHR(acc, 12), MAXINT16); /* shift right acc to get it back in Q0 and check overflow on 16 bits */ } return; } /*****************************************************************************/ /* correlateVectors : compute the correlations between two vectors of */ /* L_SUBFRAME length: c[i] = Sum(x[j]*y[j-i]) j in [i, L_SUBFRAME[ */ /* parameters: */ /* -(i) x : L_SUBFRAME length input vector on 16 bits */ /* -(i) y : L_SUBFRAME length input vector on 16 bits */ /* -(o) c : L_SUBFRAME length output vector on 32 bits */ /* */ /*****************************************************************************/ void correlateVectors (word16_t x[], word16_t y[], word32_t c[]) { int i,j; for (i=0; iQ24, previousGainPredictionError in Q10 and MAPredictionCoefficients in Q0.14*/ acc = SHL(acc,8); /* acc in Q24 to match the fixed point of next accumulations */ for (i=0; i<4; i++) { acc = MAC16_16(acc, previousGainPredictionError[i], MAPredictionCoefficients[i]); } /* acc range [10, 65] -> Q6.24 */ /* compute eq71, we already have the exposant in acc so */ /* g'c = 10^(acc/20) */ /* = 2^((acc*ln(10))/(20*ln(2))) */ /* = 2^(0,1661*acc) */ acc = SHR(acc,2); /* Q24->Q22 */ acc = MULT16_32_Q15(5442, acc); /* 5442 is 0.1661 in Q15 -> acc now in Q4.22 range [1.6, 10.8] */ acc = PSHR(acc,11); /* get acc in Q4.11 */ return g729Exp2_Q11Q16((word16_t)acc); /* acc fits on 16 bits, cast it to word16_t to send it to the exp2 function, output in Q16*/ } /*****************************************************************************/ /* computeGainPredictionError : apply eq72 to compute current fixed Codebook */ /* gain prediction error and store the result in the adhoc array */ /* parameters : */ /* -(i) fixedCodebookGainCorrectionFactor: gamma in eq72 in Q3.12 */ /* -(i/o) previousGainPredictionError: array to be updated in Q10 */ /* */ /*****************************************************************************/ void computeGainPredictionError(word16_t fixedCodebookGainCorrectionFactor, word16_t *previousGainPredictionError) { /* need to compute eq72: 20log10(fixedCodebookGainCorrectionFactor) */ /* = (20/log2(10))*log2(fixedCodebookGainCorrectionFactor) */ /* = 6.0206*log2(fixedCodebookGainCorrectionFactor) */ /* log2 input in Q0, output in Q16,fixedCodebookGainCorrectionFactor being in Q12, we shall substract 12 in Q16(786432) to the result of log2 function -> final result in Q2.16 */ word32_t currentGainPredictionError = SUB32(g729Log2_Q0Q16(fixedCodebookGainCorrectionFactor), 786432); currentGainPredictionError = PSHR(MULT16_32_Q12(24660, currentGainPredictionError),6); /* 24660 = 6.0206 in Q3.12 -> mult result in Q16, precise shift right to get it in Q4.10 */ /* shift the array and insert the current Prediction Error */ previousGainPredictionError[3] = previousGainPredictionError[2]; previousGainPredictionError[2] = previousGainPredictionError[1]; previousGainPredictionError[1] = previousGainPredictionError[0]; previousGainPredictionError[0] = (word16_t)currentGainPredictionError; } /*** bitStream to parameters Array conversions functions ***/ /* Note: these functions are in utils.c because used by test source code too */ /*****************************************************************************/ /* parametersArray2BitStream : convert array of parameters to bitStream */ /* according to spec 4 - Table 8 and following mapping of values */ /* 0 -> L0 (1 bit) */ /* 1 -> L1 (7 bits) */ /* 2 -> L2 (5 bits) */ /* 3 -> L3 (5 bits) */ /* 4 -> P1 (8 bit) */ /* 5 -> P0 (1 bits) */ /* 6 -> C1 (13 bits) */ /* 7 -> S1 (4 bits) */ /* 8 -> GA1(3 bits) */ /* 9 -> GB1(4 bits) */ /* 10 -> P2 (5 bits) */ /* 11 -> C2 (13 bits) */ /* 12 -> S2 (4 bits) */ /* 13 -> GA2(3 bits) */ /* 14 -> GB2(4 bits) */ /* parameters: */ /* -(i) parameters : 16 values parameters array */ /* -(o) bitStream : the 16 values streamed on 80 bits in a */ /* 10*8bits values array */ /* */ /*****************************************************************************/ void parametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[]) { bitStream[0] = ((parameters[0]&((uint16_t) 0x1))<<7) | (parameters[1]&((uint16_t) 0x7f)); bitStream[1] = ((parameters[2]&((uint16_t) 0x1f))<<3) | ((parameters[3]>>2)&((uint16_t) 0x7)); bitStream[2] = ((parameters[3]&((uint16_t) 0x3))<<6) | ((parameters[4]>>2)&((uint16_t) 0x3f)); bitStream[3] = ((parameters[4]&((uint16_t) 0x3))<<6) | ((parameters[5]&((uint16_t) 0x1))<<5) | ((parameters[6]>>8)&((uint16_t) 0x1f)); bitStream[4] = ((parameters[6])&((uint16_t) 0xff)); bitStream[5] = ((parameters[7]&((uint16_t) 0xf))<<4) | ((parameters[8]&((uint16_t) 0x7))<<1) | ((parameters[9]>>3)&((uint16_t) 0x1)); bitStream[6] = ((parameters[9]&((uint16_t) 0x7))<<5) | (parameters[10]&((uint16_t) 0x1f)); bitStream[7] = ((parameters[11]>>5)&((uint16_t) 0xff)); bitStream[8] = ((parameters[11]&((uint16_t) 0x1f))<<3) | ((parameters[12]>>1)&((uint16_t) 0x7)); bitStream[9] = ((parameters[12]&((uint16_t) 0x1))<<7) | ((parameters[13]&((uint16_t) 0x7))<<4) | (parameters[14]&((uint16_t) 0xf)); return; } /*****************************************************************************/ /* CNGparametersArray2BitStream : convert array of parameters to bitStream */ /* according to spec B4.3 - Table B2 and following mapping of values */ /* 0 -> L0 (1 bit) */ /* 1 -> L1 (5 bits) */ /* 2 -> L2 (4 bits) */ /* 3 -> Gain (5 bits) */ /* parameters: */ /* -(i) parameters : 4 values parameters array */ /* -(o) bitStream : the 4 values streamed on 15 bits in a */ /* 2*8bits values array */ /* */ /*****************************************************************************/ void CNGparametersArray2BitStream(uint16_t parameters[], uint8_t bitStream[]) { bitStream[0] = ((parameters[0]&((uint16_t) 0x1))<<7) | ((parameters[1]&((uint16_t) 0x1f))<<2) | ((parameters[2]>>2)&((uint16_t) 0x3)); bitStream[1] = ((parameters[2]&((uint16_t) 0x03))<<6) | ((parameters[3]&((uint16_t) 0x1f))<<1); } /*****************************************************************************/ /* parametersArray2BitStream : convert bitStream to an array of parameters */ /* reverse operation of previous funtion */ /* parameters: */ /* -(i) bitStream : the 16 values streamed on 80 bits in a */ /* 10*8bits values array */ /* -(o) parameters : 16 values parameters array */ /* */ /*****************************************************************************/ void parametersBitStream2Array(const uint8_t bitStream[], uint16_t parameters[]) { parameters[0] = (bitStream[0]>>7)&(uint16_t)0x1; parameters[1] = bitStream[0]&(uint16_t)0x7f; parameters[2] = (bitStream[1]>>3)&(uint16_t)0x1f; parameters[3] = (((uint16_t)bitStream[1]&(uint16_t)0x7)<<2) | ((bitStream[2]>>6)&(uint16_t)0x3); parameters[4] = (((uint16_t)bitStream[2])&(uint16_t)0x3f)<<2 | ((bitStream[3]>>6)&(uint16_t)0x3);; parameters[5] = (bitStream[3]>>5)&(uint16_t)0x1; parameters[6] = (((uint16_t)(bitStream[3]&(uint16_t)0x1f))<<8)| bitStream[4]; parameters[7] = (bitStream[5]>>4)&(uint16_t)0xf; parameters[8] = (bitStream[5]>>1)&(uint16_t)0x7; parameters[9] = (((uint16_t)bitStream[5]&(uint16_t)0x1)<<3)|((bitStream[6]>>5)&(uint16_t)0x7); parameters[10]= (uint16_t)bitStream[6]&(uint16_t)0x1f; parameters[11]= (((uint16_t)bitStream[7])<<5)|((bitStream[8]>>3)&(uint16_t)0x1f); parameters[12]= ((bitStream[8]&(uint16_t)0x7)<<1) | ((bitStream[9]>>7)&(uint16_t)0x1); parameters[13]= (bitStream[9]>>4)&(uint16_t)0x7; parameters[14]= bitStream[9]&(uint16_t)0xf; return; } /*****************************************************************************/ /* pseudoRandom : generate pseudo random number as in spec 4.4.4 eq96 */ /* parameters: */ /* -(i/o) randomGeneratorSeed(updated by this function) */ /* return value : */ /* - a unsigned 16 bits pseudo random number */ /* */ /*****************************************************************************/ uint16_t pseudoRandom(uint16_t *randomGeneratorSeed) { /* pseudoRandomSeed is stored in an uint16_t var, we shall not worry about overflow here */ /* pseudoRandomSeed*31821 + 13849; */ *randomGeneratorSeed = MAC16_16(13849, (*randomGeneratorSeed), 31821); return *randomGeneratorSeed; }