Browse Source

Fix compilation for Windows Phone 8.

pull/1/head
Ghislain MARY 12 years ago
parent
commit
860c8544e8
23 changed files with 336 additions and 195 deletions
  1. +9
    -3
      include/bcg729/decoder.h
  2. +9
    -3
      include/bcg729/encoder.h
  3. +12
    -11
      include/g729FixedPointMath.h
  4. +9
    -2
      include/utils.h
  5. +40
    -8
      msbcg729/bcg729_dec.c
  6. +52
    -10
      msbcg729/bcg729_enc.c
  7. +10
    -7
      src/LP2LSPConversion.c
  8. +13
    -14
      src/LSPQuantization.c
  9. +9
    -6
      src/adaptativeCodebookSearch.c
  10. +3
    -1
      src/computeAdaptativeCodebookGain.c
  11. +8
    -9
      src/computeLP.c
  12. +2
    -1
      src/computeWeightedSpeech.c
  13. +3
    -3
      src/decodeAdaptativeCodeVector.c
  14. +1
    -1
      src/decodeFixedCodeVector.c
  15. +8
    -4
      src/decodeGains.c
  16. +4
    -2
      src/decodeLSP.c
  17. +14
    -12
      src/decoder.c
  18. +20
    -16
      src/encoder.c
  19. +25
    -14
      src/findOpenLoopPitchDelay.c
  20. +26
    -23
      src/fixedCodebookSearch.c
  21. +24
    -18
      src/gainQuantization.c
  22. +32
    -26
      src/postFilter.c
  23. +3
    -1
      src/utils.c

+ 9
- 3
include/bcg729/decoder.h View File

@ -23,13 +23,19 @@
typedef struct bcg729DecoderChannelContextStruct_struct bcg729DecoderChannelContextStruct;
#include <stdint.h>
#ifdef _MSC_VER
#define BCG729_VISIBILITY
#else
#define BCG729_VISIBILITY __attribute__ ((visibility ("default")))
#endif
/*****************************************************************************/
/* initBcg729DecoderChannel : create context structure and initialise it */
/* return value : */
/* - the decoder channel context data */
/* */
/*****************************************************************************/
__attribute__ ((visibility ("default"))) bcg729DecoderChannelContextStruct *initBcg729DecoderChannel();
BCG729_VISIBILITY bcg729DecoderChannelContextStruct *initBcg729DecoderChannel();
/*****************************************************************************/
/* closeBcg729DecoderChannel : free memory of context structure */
@ -37,7 +43,7 @@ __attribute__ ((visibility ("default"))) bcg729DecoderChannelContextStruct *init
/* -(i) decoderChannelContext : the channel context data */
/* */
/*****************************************************************************/
__attribute__ ((visibility ("default"))) void closeBcg729DecoderChannel(bcg729DecoderChannelContextStruct *decoderChannelContext);
BCG729_VISIBILITY void closeBcg729DecoderChannel(bcg729DecoderChannelContextStruct *decoderChannelContext);
/*****************************************************************************/
/* bcg729Decoder : */
@ -48,5 +54,5 @@ __attribute__ ((visibility ("default"))) void closeBcg729DecoderChannel(bcg729De
/* -(o) signal : a decoded frame 80 samples (16 bits PCM) */
/* */
/*****************************************************************************/
__attribute__ ((visibility ("default"))) void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t frameErasureFlag, int16_t signal[]);
BCG729_VISIBILITY void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t frameErasureFlag, int16_t signal[]);
#endif /* ifndef DECODER_H */

+ 9
- 3
include/bcg729/encoder.h View File

@ -23,13 +23,19 @@
#include <stdint.h>
typedef struct bcg729EncoderChannelContextStruct_struct bcg729EncoderChannelContextStruct;
#ifdef _MSC_VER
#define BCG729_VISIBILITY
#else
#define BCG729_VISIBILITY __attribute__ ((visibility ("default")))
#endif
/*****************************************************************************/
/* initBcg729EncoderChannel : create context structure and initialise it */
/* return value : */
/* - the encoder channel context data */
/* */
/*****************************************************************************/
__attribute__ ((visibility ("default"))) bcg729EncoderChannelContextStruct *initBcg729EncoderChannel();
BCG729_VISIBILITY bcg729EncoderChannelContextStruct *initBcg729EncoderChannel();
/*****************************************************************************/
/* closeBcg729EncoderChannel : free memory of context structure */
@ -37,7 +43,7 @@ __attribute__ ((visibility ("default"))) bcg729EncoderChannelContextStruct *init
/* -(i) encoderChannelContext : the channel context data */
/* */
/*****************************************************************************/
__attribute__ ((visibility ("default"))) void closeBcg729EncoderChannel(bcg729EncoderChannelContextStruct *encoderChannelContext);
BCG729_VISIBILITY void closeBcg729EncoderChannel(bcg729EncoderChannelContextStruct *encoderChannelContext);
/*****************************************************************************/
/* bcg729Encoder : */
@ -48,5 +54,5 @@ __attribute__ ((visibility ("default"))) void closeBcg729EncoderChannel(bcg729En
/* on 80 bits (5 16bits words) */
/* */
/*****************************************************************************/
__attribute__ ((visibility ("default"))) void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t inputFrame[], uint8_t bitStream[]);
BCG729_VISIBILITY void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t inputFrame[], uint8_t bitStream[]);
#endif /* ifndef ENCODER_H */

+ 12
- 11
include/g729FixedPointMath.h View File

@ -59,7 +59,7 @@
/* - the log2(x) in Q16 on 32 bits */
/* */
/*****************************************************************************/
static inline word32_t g729Log2_Q0Q16(word32_t x)
static BCG729_INLINE word32_t g729Log2_Q0Q16(word32_t x)
{
/* first get the integer part and put it in the 16 MSB of return value (in Q16) */
uint16_t leadingZeros = countLeadingZeros(x); /* note: MSB is excluded as considered as sign bit */
@ -103,7 +103,7 @@ static inline word32_t g729Log2_Q0Q16(word32_t x)
/* - exp2(x) in Q16 on 32 bits */
/* */
/*****************************************************************************/
static inline word32_t g729Exp2_Q11Q16(word16_t x)
static BCG729_INLINE word32_t g729Exp2_Q11Q16(word16_t x)
{
int integer;
word16_t frac;
@ -134,11 +134,12 @@ static inline word32_t g729Exp2_Q11Q16(word16_t x)
/* - sqrt(x) in Q7 on 32 bits */
/* */
/*****************************************************************************/
static inline word32_t g729Sqrt_Q0Q7(word32_t x)
static BCG729_INLINE word32_t g729Sqrt_Q0Q7(word32_t x)
{
if (x==0) return 0;
int k;
word32_t rt;
if (x==0) return 0;
/* set x in Q14 in range [0.25,1[ */
k = (18-countLeadingZeros(x))>>1;
x = VSHR32(x, (k<<1)); /* x = x.2^-2k */
@ -159,7 +160,7 @@ static inline word32_t g729Sqrt_Q0Q7(word32_t x)
/* - 1/sqrt(x) in Q31 on 32 bits in range [43341/2^31, MAXINT32] */
/* */
/*****************************************************************************/
static inline word32_t g729InvSqrt_Q0Q31(word32_t x)
static BCG729_INLINE word32_t g729InvSqrt_Q0Q31(word32_t x)
{
if (x==1) return MAXINT32;
return (word32_t)(DIV32_32_Q24(g729Sqrt_Q0Q7(x),x)); /* sqrt(x) in Q7 + Q24 -> Q31 */
@ -185,7 +186,7 @@ static inline word32_t g729InvSqrt_Q0Q31(word32_t x)
/* - cos(x) in Q0.15 on 16 bits in range [-1, 1[ */
/* */
/*****************************************************************************/
static inline word16_t g729Cos_Q13Q15(word16_t x)
static BCG729_INLINE word16_t g729Cos_Q13Q15(word16_t x)
{
/* input var x in Q2.13 and in ]0, Pi[ */
word16_t x2,xScaled;
@ -231,22 +232,22 @@ static inline word16_t g729Cos_Q13Q15(word16_t x)
/* - atan(x) in Q2.13 on 16 bits in range ]-Pi/2(12868), Pi/2(12868)[ */
/* */
/*****************************************************************************/
static inline word16_t g729Atan_Q15Q13(word32_t x)
static BCG729_INLINE word16_t g729Atan_Q15Q13(word32_t x)
{
/* constants for rational polynomial */
word32_t angle;
word16_t x2;
int highSegment = 0;
int sign = 0;
int complement = 0;
/* make argument positive */
int sign = 0;
if (x < 0) {
x = NEG16(x);
sign = 1;
}
/* limit argument to 0..1 */
int complement = 0;
if(x > ONE_IN_Q15){
complement = 1;
x = DIV32(ONE_IN_Q30, x); /* 1/x in Q15 */
@ -295,7 +296,7 @@ static inline word16_t g729Atan_Q15Q13(word32_t x)
/* - asin(x) in Q2.13 on 16 bits in range ]-Pi/2(12868), Pi/2(12868)[ */
/* */
/*****************************************************************************/
static inline word16_t g729Asin_Q15Q13(word16_t x)
static BCG729_INLINE word16_t g729Asin_Q15Q13(word16_t x)
{
return g729Atan_Q15Q13(DIV32(SHL(x,15), PSHR(g729Sqrt_Q0Q7(SUB32(ONE_IN_Q30, MULT16_16(x,x))),7))); /* atan(x/sqrt(1.0 - x*x)) */
}
@ -308,7 +309,7 @@ static inline word16_t g729Asin_Q15Q13(word16_t x)
/* - acos(x) in Q2.13 on 16 bits in range ]0, Pi(25736)[ */
/* */
/*****************************************************************************/
static inline word16_t g729Acos_Q15Q13(word16_t x)
static BCG729_INLINE word16_t g729Acos_Q15Q13(word16_t x)
{
return(HALF_PI_Q13 - g729Asin_Q15Q13(x));
}


+ 9
- 2
include/utils.h View File

@ -21,6 +21,13 @@
#ifndef UTILS_H
#define UTILS_H
#ifdef _MSC_VER
#define BCG729_INLINE __inline
#else
#define BCG729_INLINE inline
#endif
/*****************************************************************************/
/* insertionSort : sort an array in growing order using insertion algorithm */
/* parameters : */
@ -87,10 +94,10 @@ void correlateVectors (word16_t x[], word16_t y[], word32_t c[]);
/* - number of heading zeros(MSB excluded. Ex: 0x0080 00000 returns 7) */
/* */
/*****************************************************************************/
static inline uint16_t countLeadingZeros(word32_t x)
static BCG729_INLINE uint16_t countLeadingZeros(word32_t x)
{
if (x==0) return 31;
uint16_t leadingZeros = 0;
if (x==0) return 31;
while (x<(word32_t)0x40000000) {
leadingZeros++;
x <<=1;


+ 40
- 8
msbcg729/bcg729_dec.c View File

@ -94,21 +94,53 @@ static MSFilterMethod filter_methods[]={
};
#define MS_BCG729_DEC_ID MS_FILTER_PLUGIN_ID
#define MS_BCG729_DEC_NAME "MSBCG729Dec"
#define MS_BCG729_DEC_DESCRIPTION "G729 audio decoder filter"
#define MS_BCG729_DEC_CATEGORY MS_FILTER_DECODER
#define MS_BCG729_DEC_ENC_FMT "G729"
#define MS_BCG729_DEC_NINPUTS 1
#define MS_BCG729_DEC_NOUTPUTS 1
#define MS_BCG729_DEC_FLAGS MS_FILTER_IS_PUMP
#ifndef _MSC_VER
MSFilterDesc ms_bcg729_dec_desc={
.id=MS_FILTER_PLUGIN_ID, /* from Allfilters.h*/
.name="MSBCG729Dec",
.text="G729 decoder filter.",
.category=MS_FILTER_DECODER,
.enc_fmt="G729",
.ninputs=1, /*number of inputs*/
.noutputs=1, /*number of outputs*/
.id=MS_BCG729_DEC_ID,
.name=MS_BCG729_DEC_NAME,
.text=MS_BCG729_DEC_DESCRIPTION,
.category=MS_BCG729_DEC_CATEGORY,
.enc_fmt=MS_BCG729_DEC_ENC_FMT,
.ninputs=MS_BCG729_DEC_NINPUTS, /*number of inputs*/
.noutputs=MS_BCG729_DEC_NOUTPUTS, /*number of outputs*/
.init=filter_init,
.preprocess=filter_preprocess,
.process=filter_process,
.postprocess=filter_postprocess,
.uninit=filter_uninit,
.methods=filter_methods,
.flags=MS_FILTER_IS_PUMP
.flags=MS_BCG729_DEC_FLAGS
};
#else
MSFilterDesc ms_bcg729_dec_desc={
MS_BCG729_DEC_ID,
MS_BCG729_DEC_NAME,
MS_BCG729_DEC_DESCRIPTION,
MS_BCG729_DEC_CATEGORY,
MS_BCG729_DEC_ENC_FMT,
MS_BCG729_DEC_NINPUTS,
MS_BCG729_DEC_NOUTPUTS,
filter_init,
filter_preprocess,
filter_process,
filter_postprocess,
filter_uninit,
filter_methods,
MS_BCG729_DEC_FLAGS
};
#endif
MS_FILTER_DESC_EXPORT(ms_bcg729_dec_desc)

+ 52
- 10
msbcg729/bcg729_enc.c View File

@ -32,8 +32,9 @@ struct bcg729Encoder_struct {
};
static void filter_init(MSFilter *f){
struct bcg729Encoder_struct* obj;
f->data = ms_new0(struct bcg729Encoder_struct,1);
struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data;
obj = (struct bcg729Encoder_struct*) f->data;
obj->ptime=20;
obj->max_ptime=100;
}
@ -119,29 +120,70 @@ static MSFilterMethod filter_methods[]={
};
#define MS_BCG729_ENC_ID MS_FILTER_PLUGIN_ID
#define MS_BCG729_ENC_NAME "MSBCG729Enc"
#define MS_BCG729_ENC_DESCRIPTION "G729 audio encoder filter"
#define MS_BCG729_ENC_CATEGORY MS_FILTER_ENCODER
#define MS_BCG729_ENC_ENC_FMT "G729"
#define MS_BCG729_ENC_NINPUTS 1
#define MS_BCG729_ENC_NOUTPUTS 1
#define MS_BCG729_ENC_FLAGS 0
#ifndef _MSC_VER
MSFilterDesc ms_bcg729_enc_desc={
.id=MS_FILTER_PLUGIN_ID, /* from Allfilters.h*/
.name="MSBCG729Enc",
.text="G729 audio encoder filter.",
.category=MS_FILTER_ENCODER,
.enc_fmt="G729",
.ninputs=1, /*number of inputs*/
.noutputs=1, /*number of outputs*/
.id=MS_BCG729_ENC_ID,
.name=MS_BCG729_ENC_NAME,
.text=MS_BCG729_ENC_DESCRIPTION,
.category=MS_BCG729_ENC_CATEGORY,
.enc_fmt=MS_BCG729_ENC_ENC_FMT,
.ninputs=MS_BCG729_ENC_NINPUTS, /*number of inputs*/
.noutputs=MS_BCG729_ENC_NOUTPUTS, /*number of outputs*/
.init=filter_init,
.preprocess=filter_preprocess,
.process=filter_process,
.postprocess=filter_postprocess,
.uninit=filter_uninit,
.methods=filter_methods
.methods=filter_methods,
.flags=MS_BCG729_ENC_FLAGS
};
#else
MSFilterDesc ms_bcg729_enc_desc={
MS_BCG729_ENC_ID,
MS_BCG729_ENC_NAME,
MS_BCG729_ENC_DESCRIPTION,
MS_BCG729_ENC_CATEGORY,
MS_BCG729_ENC_ENC_FMT,
MS_BCG729_ENC_NINPUTS,
MS_BCG729_ENC_NOUTPUTS,
filter_init,
filter_preprocess,
filter_process,
filter_postprocess,
filter_uninit,
filter_methods,
MS_BCG729_ENC_FLAGS
};
#endif
MS_FILTER_DESC_EXPORT(ms_bcg729_enc_desc)
#ifdef _MSC_VER
#define MS_PLUGIN_DECLARE(type) __declspec(dllexport) type
#else
#define MS_PLUGIN_DECLARE(type) type
#endif
extern MSFilterDesc ms_bcg729_dec_desc;
#ifndef VERSION
#define VERSION "debug"
#endif
void libmsbcg729_init(){
MS_PLUGIN_DECLARE(void) libmsbcg729_init(void){
ms_filter_register(&ms_bcg729_enc_desc);
ms_filter_register(&ms_bcg729_dec_desc);
ms_message(" libmsbcg729 " VERSION " plugin loaded");


+ 10
- 7
src/LP2LSPConversion.c View File

@ -42,10 +42,14 @@ static const word16_t cosW0pi[NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL]; /* cos(w
int LP2LSPConversion(word16_t LPCoefficients[], word16_t LSPCoefficients[])
{
uint8_t i;
/*** Compute the polynomials coefficients according to spec 3.2.3 eq15 ***/
word32_t f1[6];
word32_t f2[6]; /* coefficients for polynomials F1 anf F2 in Q12 for computation, then converted in Q15 for the Chebyshev Polynomial function */
uint8_t numberOfRootFound = 0; /* used to check the final number of roots found and exit the loop on each polynomial computation when we have 10 roots */
word32_t *polynomialCoefficients;
word32_t previousCx;
word32_t Cx; /* value of Chebyshev Polynomial at current point in Q15 */
/*** Compute the polynomials coefficients according to spec 3.2.3 eq15 ***/
f1[0] = ONE_IN_Q12; /* values 0 are not part of the output, they are just used for computation purpose */
f2[0] = ONE_IN_Q12;
/* for (i = 0; i< 5; i++) { */
@ -64,10 +68,8 @@ int LP2LSPConversion(word16_t LPCoefficients[], word16_t LSPCoefficients[])
/*** Compute at each step(50 steps for the AnnexA version) the Chebyshev polynomial to find the 10 roots ***/
/* start using f1 polynomials coefficients and altern with f2 after founding each root (spec 3.2.3 eq13 and eq14) */
uint8_t numberOfRootFound = 0; /* used to check the final number of roots found and exit the loop on each polynomial computation when we have 10 roots */
word32_t *polynomialCoefficients = f1; /* start with f1 coefficients */
word32_t previousCx = ChebyshevPolynomial(cosW0pi[0], polynomialCoefficients); /* compute the first point and store it as the previous value for polynomial */
word32_t Cx; /* value of Chebyshev Polynomial at current point in Q15 */
polynomialCoefficients = f1; /* start with f1 coefficients */
previousCx = ChebyshevPolynomial(cosW0pi[0], polynomialCoefficients); /* compute the first point and store it as the previous value for polynomial */
for (i=1; i<NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL; i++) {
Cx = ChebyshevPolynomial(cosW0pi[i], polynomialCoefficients);
@ -78,8 +80,9 @@ int LP2LSPConversion(word16_t LPCoefficients[], word16_t LSPCoefficients[])
word16_t xHigh = cosW0pi[i];
word16_t xMean;
for (j=0; j<2; j++) {
word32_t middleCx;
xMean = (word16_t)SHR(ADD32(xLow, xHigh), 1);
word32_t middleCx = ChebyshevPolynomial(xMean, polynomialCoefficients); /* compute the polynome for the value in the middle of current interval */
middleCx = ChebyshevPolynomial(xMean, polynomialCoefficients); /* compute the polynome for the value in the middle of current interval */
if ((previousCx^middleCx)&0x10000000) { /* check signe change by XOR on the value of first bit */
xHigh = xMean;


+ 13
- 14
src/LSPQuantization.c View File

@ -53,16 +53,23 @@ void initLSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContex
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 ***/
word16_t LSF[NB_LSP_COEFF]; /* LSF coefficients in Q2.13 range [0, Pi[ */
for (i=0; i<NB_LSP_COEFF; i++) {
LSF[i] = g729Acos_Q15Q13(LSPCoefficients[i]);
}
/*** compute the weights vector as in spec 3.2.4 eq22 ***/
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 */
weightsThreshold[0] = SUB16(LSF[1], OO4PIPLUS1_IN_Q13);
for (i=1; i<NB_LSP_COEFF-1; i++) {
weightsThreshold[i] = SUB16(SUB16(LSF[i+1], LSF[i-1]), ONE_IN_Q13);
@ -81,16 +88,12 @@ void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, w
weights[5] = MULT16_16_Q14(weights[5], ONE_POINT_2_IN_Q14);
/*** compute the coefficients for the two MA Predictors ***/
int L0;
word32_t weightedMeanSquareError[L0_RANGE];
word16_t L1index[L0_RANGE];
word16_t L2index[L0_RANGE];
word16_t L3index[L0_RANGE];
for (L0=0; L0<L0_RANGE; L0++) {
/* compute the target Vector (l) to be quantized as in spec 3.2.4 eq23 */
word16_t targetVector[NB_LSP_COEFF]; /* vector to be quantized in Q13 */
word32_t meanSquareDiff = MAXINT32;
word16_t quantizedVector[NB_LSP_COEFF]; /* in Q13, the current state of quantized vector */
for (i=0; i<NB_LSP_COEFF; i++) {
word32_t acc = SHL(LSF[i],15); /* acc in Q2.28 */
for (j=0; j<MA_MAX_K; j++) {
@ -100,7 +103,6 @@ void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, w
}
/* find closest match for predictionError (minimize mean square diff) in L1 codebook */
word32_t meanSquareDiff = MAXINT32;
for (i=0; i<L1_RANGE; i++) {
word32_t acc = 0;
for (j=0; j<NB_LSP_COEFF; j++) {
@ -154,7 +156,6 @@ void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, w
/* compute the quantized vector L1+L2/L3 and rearrange it as specified in spec 3.2.4(first the higher part (L2) and then the lower part (L3)) */
/* Note: according to the spec, the rearrangement shall be done on each candidate while looking for best match, but the ITU code does it after picking the best match and so we do */
word16_t quantizedVector[NB_LSP_COEFF]; /* in Q13, the current state of quantized vector */
for (i=0; i<NB_LSP_COEFF/2; i++) {
quantizedVector[i] = ADD16(L1[L1index[L0]][i], L2L3[L2index[L0]][i]);
}
@ -206,8 +207,6 @@ void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, w
}
/*** Compute the quantized LSF from the L coefficients ***/
word16_t quantizerOutput[NB_LSP_COEFF];
word16_t qLSF[NB_LSP_COEFF];
/* reconstruct vector from the codebooks using the selected parameters spec 3.2.4 eq19 */
for (i=0; i<NB_LSP_COEFF/2; i++) {
quantizerOutput[i] = ADD16(L1[parameters[1]][i], L2L3[parameters[2]][i]); /* codebooks are in Q2.13 for L1 and Q0.13 for L2L3, due to actual values stored in the codebooks, result in Q2.13 */


+ 9
- 6
src/adaptativeCodebookSearch.c View File

@ -59,13 +59,13 @@ void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDela
int16_t *intPitchDelay, int16_t *fracPitchDelay, uint16_t *pitchDelayCodeword, uint16_t subFrameIndex)
{
int i,j;
word32_t backwardFilteredTargetSignal[L_SUBFRAME];
word32_t correlationMax = MININT32;
/* compute the backward Filtered Target Signal as specified in A.3.7: correlation of target signal and impulse response */
correlateVectors(targetSignal, impulseResponse, backwardFilteredTargetSignal); /* targetSignal in Q0, impulseResponse in Q12 -> backwardFilteredTargetSignal in Q12 */
/* maximise the sum as in spec A.3.7, eq A.7 */
word32_t correlationMax = MININT32;
for (i=*intPitchDelayMin; i<=*intPitchDelayMax; i++) {
word32_t correlation = 0;
for (j=0; j<L_SUBFRAME; j++) {
@ -87,6 +87,7 @@ void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDela
if (!(subFrameIndex==0 && *intPitchDelay>=85)) {
/* compute the fracPitchDelay*/
word16_t adaptativeCodebookVector[L_SUBFRAME]; /* as the adaptativeCodebookVector is computed in the excitation vector, use this buffer to backup the one giving the highest numerator */
word32_t correlation=0;
/* search the fractionnal part to get the best correlation */
/* we already have in excitationVector for fracPitchDelay = 0 the adaptativeCodebookVector (see specA.3.7) */
correlationMax = 0;
@ -98,7 +99,6 @@ void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDela
/* Fractionnal part = -1 */
generateAdaptativeCodebookVector(excitationVector, *intPitchDelay, -1);
word32_t correlation=0;
for (i=0; i<L_SUBFRAME; i++) {
correlation = MAC16_32_Q12(correlation, excitationVector[i], backwardFilteredTargetSignal[i]);
}
@ -167,6 +167,9 @@ void adaptativeCodebookSearch(word16_t excitationVector[], int16_t *intPitchDela
void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPitchDelay, int16_t fracPitchDelay)
{
int n,i,j;
word16_t *delayedExcitationVector;
word16_t *b30Increased;
word16_t *b30Decreased;
/* fracPitchDelay is in range [-1, 1], convert it to [0,2] needed by eqA.8 */
fracPitchDelay = -fracPitchDelay;
@ -176,9 +179,9 @@ void generateAdaptativeCodebookVector(word16_t excitationVector[], int16_t intPi
}
/**/
word16_t *delayedExcitationVector = &(excitationVector[-intPitchDelay]); /* delayedExcitationVector is used to address the excitation vector at index -intPitchDelay (-k in eq40) */
word16_t *b30Increased = &(b30[fracPitchDelay]); /* b30 increased points to b30[fracPitchDelay] : b30[t] in eq40. b30 in Q15 */
word16_t *b30Decreased = &(b30[3-fracPitchDelay]); /* b30 decreased points to b30[-fracPitchDelay] : b30[3-t] in eq40. b30 in Q15 */
delayedExcitationVector = &(excitationVector[-intPitchDelay]); /* delayedExcitationVector is used to address the excitation vector at index -intPitchDelay (-k in eq40) */
b30Increased = &(b30[fracPitchDelay]); /* b30 increased points to b30[fracPitchDelay] : b30[t] in eq40. b30 in Q15 */
b30Decreased = &(b30[3-fracPitchDelay]); /* b30 decreased points to b30[-fracPitchDelay] : b30[3-t] in eq40. b30 in Q15 */
for (n=0; n<L_SUBFRAME; n++) {


+ 3
- 1
src/computeAdaptativeCodebookGain.c View File

@ -41,6 +41,8 @@
word16_t computeAdaptativeCodebookGain(word16_t targetSignal[], word16_t filteredAdaptativeCodebookVector[], word64_t *gainQuantizationXy, word64_t *gainQuantizationYy)
{
int i;
word32_t gain;
*gainQuantizationXy = 0; /* contains the scalar product targetSignal, filteredAdaptativeCodebookVector : numerator */
*gainQuantizationYy = 0; /* contains the scalar product filteredAdaptativeCodebookVector^2 : denominator */
@ -56,7 +58,7 @@ word16_t computeAdaptativeCodebookGain(word16_t targetSignal[], word16_t filtere
}
/* output shall be in Q14 */
word32_t gain = DIV64(SHL64(*gainQuantizationXy,14),*gainQuantizationYy); /* gain in Q14 */
gain = DIV64(SHL64(*gainQuantizationXy,14),*gainQuantizationYy); /* gain in Q14 */
/* check if it is not above 1.2 */
if (gain>ONE_POINT_2_IN_Q14) {


+ 8
- 9
src/computeLP.c View File

@ -37,11 +37,18 @@
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[])
{
int i,j;
word16_t windowedSignal[L_LP_ANALYSIS_WINDOW];
word32_t autoCorrelationCoefficient[NB_LSP_COEFF+1];
word64_t acc64=0; /* acc on 64 bits */
int rightShiftToNormalise=0;
word32_t previousIterationLPCoefficients[NB_LSP_COEFF+1]; /* to compute a[]*/
word32_t LPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */
word32_t sum = 0; /* in Q27 */
word32_t E = 0; /* in Q31 */
/*********************************************************************/
/* Compute the windowed signal according to spec 3.2.1 eq4 */
/*********************************************************************/
word16_t windowedSignal[L_LP_ANALYSIS_WINDOW];
for (i=0; i<L_LP_ANALYSIS_WINDOW; i++) {
windowedSignal[i] = MULT16_16_P15(signal[i], wlp[i]); /* signal in Q0, wlp in Q0.15, windowedSignal in Q0 */
}
@ -49,11 +56,9 @@ void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[])
/*********************************************************************************/
/* Compute the autoCorrelation coefficients r[0..10] according to spec 3.2.1 eq5 */
/*********************************************************************************/
word32_t autoCorrelationCoefficient[NB_LSP_COEFF+1];
/* Compute autoCorrelationCoefficient[0] first as it is the highest number and normalise it on 32 bits then apply the same normalisation to the other coefficients */
/* autoCorrelationCoefficient are normalised on 32 bits and then considered as Q31 in range [-1,1[ */
/* autoCorrelationCoefficient[0] is computed on 64 bits as it is likely to overflow 32 bits */
word64_t acc64=0; /* acc on 64 bits */
for (i=0; i<L_LP_ANALYSIS_WINDOW; i++) {
acc64 = MAC64(acc64, windowedSignal[i], windowedSignal[i]);
}
@ -61,7 +66,6 @@ void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[])
acc64 = 1; /* spec 3.2.1: To avoid arithmetic problems for low-level input signals the value of r(0) has a lower boundary of r(0) = 1.0 */
}
/* normalise the acc64 on 32 bits */
int rightShiftToNormalise=0;
if (acc64>MAXINT32) {
do {
acc64 = SHR(acc64,1);
@ -125,11 +129,6 @@ void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[])
/* set to Q27 at the end of current iteration */
/* */
/*********************************************************************************/
word32_t previousIterationLPCoefficients[NB_LSP_COEFF+1]; /* to compute a[]*/
word32_t LPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */
word32_t sum = 0; /* in Q27 */
word32_t E = 0; /* in Q31 */
/* init */
LPCoefficients[0] = ONE_IN_Q27;
LPCoefficients[1] = -DIV32_32_Q27(autoCorrelationCoefficient[1], autoCorrelationCoefficient[0]); /* result in Q27(but<1) */


+ 2
- 1
src/computeWeightedSpeech.c View File

@ -47,6 +47,8 @@ void computeWeightedSpeech(word16_t inputSignal[], word16_t qLPCoefficients[], w
/* finally get the weightedInputSignal[n] = LPResidualSignal[n] - ∑(i=1..10)qLP'[i]*weightedInputSignal[n-i] spec A3.3.3 eqA.2 */
int i,j;
word16_t weightedqLPLowPassCoefficients[NB_LSP_COEFF]; /* in Q12 */
/*** compute LPResisualSignal (spec A3.3.3 eqA.3) in Q0 ***/
/* compute residual signal for the first subframe: use the first 10 qLPCoefficients */
for (i=0; i<L_SUBFRAME; i++) {
@ -67,7 +69,6 @@ void computeWeightedSpeech(word16_t inputSignal[], word16_t qLPCoefficients[], w
/*** compute weightedqLPLowPassCoefficients and weightedInputSignal for first subframe ***/
/* spec A3.3.3 a' = weightedqLPLowPassCoefficients[i] = weightedqLP[i] - 0.7*weightedqLP[i-1] */
word16_t weightedqLPLowPassCoefficients[NB_LSP_COEFF]; /* in Q12 */
weightedqLPLowPassCoefficients[0] = SUB16(weightedqLPCoefficients[0],O7_IN_Q12); /* weightedqLP[-1] = 1 -> weightedqLPLowPassCoefficients[0] = weightedqLPCoefficients[0] - 0.7 */
for (i=1; i<NB_LSP_COEFF; i++) {
weightedqLPLowPassCoefficients[i] = SUB16(weightedqLPCoefficients[i], MULT16_16_Q12(weightedqLPCoefficients[i-1], O7_IN_Q12));


+ 3
- 3
src/decodeAdaptativeCodeVector.c View File

@ -55,6 +55,9 @@ void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChanne
int16_t *intPitchDelay, word16_t *excitationVector)
{
int16_t fracPitchDelay;
word16_t *excitationVectorMinusK; /* pointer to u(-k) */
int n;
/*** Compute the Pitch Delay from the Codebook index ***/
/* fracPitchDelay is computed in the range -1,0,1 */
if (subFrameIndex == 0 ) { /* first subframe */
@ -114,8 +117,6 @@ void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChanne
/* v the adaptative codebook vector */
/* b30 an interpolation filter */
word16_t *excitationVectorMinusK; /* pointer to u(-k) */
/* scale fracPichDelay from -1,0.1 to 0,1,2 */
if (fracPitchDelay==1) {
excitationVectorMinusK = &(excitationVector[-(*intPitchDelay+1)]); /* fracPitchDelay being positive -> increase by one the integer part and set to 2 the fractional part : -(k+1/3) -> -(k+1)+2/3 */
@ -125,7 +126,6 @@ void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChanne
excitationVectorMinusK = &(excitationVector[-(*intPitchDelay)]); /* -(k-1/3) -> -k+1/3 or -(k) -> -k*/
}
int n;
for (n=0; n<L_SUBFRAME; n++) { /* loop over the whole subframe */
word16_t *excitationVectorNMinusK = &(excitationVectorMinusK[n]); /* point to u(n-k), unscaled value, full range */
word16_t *excitationVectorNMinusKPlusOne = &(excitationVectorMinusK[n+1]); /* point to u(n-k+1), unscaled value, full range */


+ 1
- 1
src/decodeFixedCodeVector.c View File

@ -38,6 +38,7 @@ void decodeFixedCodeVector(uint16_t signs, uint16_t positions, int16_t intPitchD
{
uint16_t positionsArray[4];
uint16_t jx;
int i;
/* get the positions into an array: mapping according to eq62 and table7 in spec 3.8 */
positionsArray[0] = (positions&(uint16_t)7)*5; /* m0 = 5*C, do not use macro here as whatever fixed or floating point computation we use, these are integers */
@ -51,7 +52,6 @@ void decodeFixedCodeVector(uint16_t signs, uint16_t positions, int16_t intPitchD
positionsArray[3] = ((positions&(uint16_t)7)*5) + 3 + jx; /* m3 = 5*C + 3 + jx, do not use macro here as whatever fixed or floating point computation we use, these are integers */
/* initialise the output Vector */
int i;
for (i=0; i<L_SUBFRAME; i++) {
fixedCodebookVector[i]=0;
}


+ 8
- 4
src/decodeGains.c View File

@ -55,8 +55,14 @@ void initDecodeGains(bcg729DecoderChannelContextStruct *decoderChannelContext)
void decodeGains (bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_t GA, uint16_t GB, word16_t *fixedCodebookVector, uint8_t frameErasureFlag,
word16_t *adaptativeCodebookGain, word16_t *fixedCodebookGain)
{
word32_t predictedFixedCodebookGain;
word16_t fixedCodebookGainCorrectionFactor;
/* check the erasure flag */
if (frameErasureFlag != 0) { /* we have a frame erasure, proceed as described in spec 4.4.2 */
int i;
word32_t currentGainPredictionError =0;
/* adaptativeCodebookGain as in eq94 */
if (*adaptativeCodebookGain < 16384) { /* last subframe gain < 1 in Q14 */
*adaptativeCodebookGain = MULT16_16_Q15(*adaptativeCodebookGain, 29491 ); /* *0.9 in Q15 */
@ -67,8 +73,6 @@ void decodeGains (bcg729DecoderChannelContextStruct *decoderChannelContext, uint
*fixedCodebookGain = MULT16_16_Q15(*fixedCodebookGain, 32113 ); /* *0.98 in Q15 */
/* And update the previousGainPredictionError according to spec 4.4.3 */
int i;
word32_t currentGainPredictionError =0;
for (i=0; i<4; i++) {
currentGainPredictionError = ADD32(currentGainPredictionError, decoderChannelContext->previousGainPredictionError[i]); /* previousGainPredictionError in Q3.10-> Sum in Q5.10 (on 32 bits) */
}
@ -98,10 +102,10 @@ void decodeGains (bcg729DecoderChannelContextStruct *decoderChannelContext, uint
*adaptativeCodebookGain = ADD16(GACodebook[GA][0], GBCodebook[GB][0]); /* result in Q1.14 */
/* Fixed Codebook: MA code-gain prediction */
word32_t predictedFixedCodebookGain = MACodeGainPrediction(decoderChannelContext->previousGainPredictionError, fixedCodebookVector); /* predictedFixedCodebookGain on 32 bits in Q11.16 */
predictedFixedCodebookGain = MACodeGainPrediction(decoderChannelContext->previousGainPredictionError, fixedCodebookVector); /* predictedFixedCodebookGain on 32 bits in Q11.16 */
/* get fixed codebook gain correction factor(gama) from the codebooks GA and GB according to eq74 */
word16_t fixedCodebookGainCorrectionFactor = ADD16(GACodebook[GA][1], GBCodebook[GB][1]); /* result in Q3.12 (range [0.185, 5.05])*/
fixedCodebookGainCorrectionFactor = ADD16(GACodebook[GA][1], GBCodebook[GB][1]); /* result in Q3.12 (range [0.185, 5.05])*/
/* compute fixedCodebookGain according to eq74 */
*fixedCodebookGain = (word16_t)PSHR(MULT16_32_Q12(fixedCodebookGainCorrectionFactor, predictedFixedCodebookGain), 15); /* Q11.16*Q3.12 -> Q14.16, shift by 15 to get a Q14.1 which fits on 16 bits */


+ 4
- 2
src/decodeLSP.c View File

@ -65,6 +65,8 @@ void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_
if (frameErased == 0) { /* frame is ok, proceed according to 3.2.4 section of the doc */
word32_t acc; /* Accumulator in Q2.28 */
/*** doc 3.2.4 eq(19) ***/
/* get the L codewords from the codebooks L1, L2 and L3 */
/* for easier implementation, L2 and L3 5 dimensional codebooks have been stored in one 10 dimensional L2L3 codebook */
@ -90,7 +92,6 @@ void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_
/* currentqLSF and previousLCodeWord in Q2.13 */
/* MAPredictor and MAPredictorSum in Q0.15 with MAPredictorSum[MA switch][i]+Sum[j=0-3](MAPredictor[MA switch][j][i])=1 -> acc will end up being in Q2.28*/
/* Note : previousLCodeWord array containing the last 4 code words is updated during this phase */
word32_t acc; /* Accumulator in Q2.28 */
for (i=0; i<NB_LSP_COEFF; i++) {
acc = MULT16_16(MAPredictorSum[L[0]][i], currentqLSF[i]);
@ -134,12 +135,13 @@ void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_
} else { /* frame erased indicator is set, proceed according to section 4.4 of the specs */
word32_t acc; /* acc in Q2.28 */
/* restore the qLSF of last valid frame */
for (i=0; i<NB_LSP_COEFF; i++) {
currentqLSF[i] = decoderChannelContext->lastqLSF[i];
}
word32_t acc; /* acc in Q2.28 */
/* compute back the codewords from the qLSF and store them in the previousLCodeWord buffer */
for (i=0; i<NB_LSP_COEFF; i++) { /* currentqLSF and previousLCodeWord in Q2.13, MAPredictor in Q0.15 and invMAPredictorSum in Q3.12 */
acc = SHL(decoderChannelContext->lastqLSF[i],15); /* Q2.13 -> Q2.28 */


+ 14
- 12
src/decoder.c View File

@ -99,6 +99,19 @@ void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uin
int i;
uint16_t parameters[NB_PARAMETERS];
/* internal buffers which we do not need to keep between calls */
word16_t qLSP[NB_LSP_COEFF]; /* store the qLSP coefficients in Q0.15 */
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* store the interpolated qLSP coefficient in Q0.15 */
word16_t LP[2*NB_LSP_COEFF]; /* store the 2 sets of LP coefficients in Q12 */
int16_t intPitchDelay; /* store the Pitch Delay in and out of decodeAdaptativeCodeVector, in for decodeFixedCodeVector */
word16_t fixedCodebookVector[L_SUBFRAME]; /* the fixed Codebook Vector in Q1.13*/
word16_t postFilteredSignal[L_SUBFRAME]; /* store the postfiltered signal in Q0 */
uint8_t parityErrorFlag;
int subframeIndex;
int parametersIndex = 4; /* this is used to select the right parameter according to the subframe currently computed, start pointing to P1 */
int LPCoefficientsIndex = 0; /* this is used to select the right LP Coefficients according to the subframe currently computed */
/*** parse the bitstream and get all parameter into an array as in spec 4 - Table 8 ***/
/* parameters buffer mapping : */
/* 0 -> L0 (1 bit) */
@ -124,14 +137,6 @@ void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uin
}
}
/* internal buffers which we do not need to keep between calls */
word16_t qLSP[NB_LSP_COEFF]; /* store the qLSP coefficients in Q0.15 */
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* store the interpolated qLSP coefficient in Q0.15 */
word16_t LP[2*NB_LSP_COEFF]; /* store the 2 sets of LP coefficients in Q12 */
int16_t intPitchDelay; /* store the Pitch Delay in and out of decodeAdaptativeCodeVector, in for decodeFixedCodeVector */
word16_t fixedCodebookVector[L_SUBFRAME]; /* the fixed Codebook Vector in Q1.13*/
word16_t postFilteredSignal[L_SUBFRAME]; /* store the postfiltered signal in Q0 */
/*****************************************************************************************/
/*** on frame basis : decodeLSP, interpolate them with previous ones and convert to LP ***/
@ -150,12 +155,9 @@ void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uin
qLSP2LP(qLSP, &(LP[NB_LSP_COEFF]));
/* check the parity on the adaptativeCodebookIndexSubframe1(P1) with the received one (P0)*/
uint8_t parityErrorFlag = (uint8_t)(computeParity(parameters[4]) ^ parameters[5]);
parityErrorFlag = (uint8_t)(computeParity(parameters[4]) ^ parameters[5]);
/* loop over the two subframes */
int subframeIndex;
int parametersIndex = 4; /* this is used to select the right parameter according to the subframe currently computed, start pointing to P1 */
int LPCoefficientsIndex = 0; /* this is used to select the right LP Coefficients according to the subframe currently computed */
for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) {
/* decode the adaptative Code Vector */
decodeAdaptativeCodeVector( decoderChannelContext,


+ 20
- 16
src/encoder.c View File

@ -108,6 +108,13 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
word16_t qLSPCoefficients[NB_LSP_COEFF]; /* the quantized LSP coefficients in Q15 */
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* the interpolated qLSP used for first subframe in Q15 */
uint16_t openLoopPitchDelay;
int16_t intPitchDelayMin;
int16_t intPitchDelayMax;
int subframeIndex;
int LPCoefficientsIndex = 0;
int parametersIndex = 4; /* index to insert parameters in the parameters output array */
word16_t impulseResponseInput[L_SUBFRAME]; /* input buffer for the impulse response computation: in Q12, 1 followed by all zeros see spec A3.5*/
/*****************************************************************************************/
/*** on frame basis : preProcessing, LP Analysis, Open-loop pitch search ***/
@ -162,14 +169,14 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
computeWeightedSpeech(encoderChannelContext->signalCurrentFrame, qLPCoefficients, weightedqLPCoefficients, &(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY]), &(encoderChannelContext->excitationVector[L_PAST_EXCITATION])); /* weightedInputSignal contains MAXIMUM_INT_PITCH_DELAY values from previous frame, points to current frame */
/*** find the open loop pitch delay ***/
uint16_t openLoopPitchDelay = findOpenLoopPitchDelay(&(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY]));
openLoopPitchDelay = findOpenLoopPitchDelay(&(encoderChannelContext->weightedInputSignal[MAXIMUM_INT_PITCH_DELAY]));
/* define boundaries for closed loop pitch delay search as specified in 3.7 */
int16_t intPitchDelayMin = openLoopPitchDelay-3;
intPitchDelayMin = openLoopPitchDelay-3;
if (intPitchDelayMin < 20) {
intPitchDelayMin = 20;
}
int16_t intPitchDelayMax = intPitchDelayMin + 6;
intPitchDelayMax = intPitchDelayMin + 6;
if (intPitchDelayMax > MAXIMUM_INT_PITCH_DELAY) {
intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY;
intPitchDelayMin = MAXIMUM_INT_PITCH_DELAY - 6;
@ -178,16 +185,21 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
/*****************************************************************************************/
/* loop over the two subframes: Closed-loop pitch search(adaptative codebook), fixed codebook, memory update */
/* set index and buffers */
int subframeIndex;
int LPCoefficientsIndex = 0;
int parametersIndex = 4; /* index to insert parameters in the parameters output array */
word16_t impulseResponseInput[L_SUBFRAME]; /* input buffer for the impulse response computation: in Q12, 1 followed by all zeros see spec A3.5*/
impulseResponseInput[0] = ONE_IN_Q12;
memset(&(impulseResponseInput[1]), 0, (L_SUBFRAME-1)*sizeof(word16_t));
for (subframeIndex=0; subframeIndex<L_FRAME; subframeIndex+=L_SUBFRAME) {
int16_t intPitchDelay, fracPitchDelay;
word16_t adaptativeCodebookGain;
/*** Compute the impulse response : filter a subframe long buffer filled with unit and only zero through the 1/weightedqLPCoefficients as in spec A.3.5 ***/
word16_t impulseResponseBuffer[NB_LSP_COEFF+L_SUBFRAME]; /* impulseResponseBuffer in Q12, need NB_LSP_COEFF as past value to go through filtering function */
word16_t filteredAdaptativeCodebookVector[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, the first NB_LSP_COEFF words are set to zero and used by filter only */
word64_t gainQuantizationXy, gainQuantizationYy; /* used to store in Q0 values reused in gain quantization */
word16_t fixedCodebookVector[L_SUBFRAME]; /* in Q13 */
word16_t convolvedFixedCodebookVector[L_SUBFRAME]; /* in Q12 */
word16_t quantizedAdaptativeCodebookGain; /* in Q14 */
word16_t quantizedFixedCodebookGain; /* in Q1 */
memset(impulseResponseBuffer, 0, (NB_LSP_COEFF)*sizeof(word16_t)); /* set the past values to zero */
synthesisFilter(impulseResponseInput, &(weightedqLPCoefficients[LPCoefficientsIndex]), &(impulseResponseBuffer[NB_LSP_COEFF]));
@ -197,7 +209,6 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
/*** Adaptative Codebook search : compute the intPitchDelay, fracPitchDelay and associated parameter, compute also the adaptative codebook vector used to generate the excitation ***/
/* after this call, the excitationVector[L_PAST_EXCITATION + subFrameIndex] contains the adaptative codebook vector as in spec 3.7.1 */
int16_t intPitchDelay, fracPitchDelay;
adaptativeCodebookSearch(&(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &intPitchDelayMin, &intPitchDelayMax, &(impulseResponseBuffer[NB_LSP_COEFF]), &(encoderChannelContext->targetSignal[NB_LSP_COEFF]),
&intPitchDelay, &fracPitchDelay, &(parameters[parametersIndex]), subframeIndex);
@ -206,13 +217,10 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
/* this computation makes use of two partial results used for gainQuantization too (yy and xy in eq63), they are part of the function output */
/* note spec 3.7.3 eq44 make use of convolution of impulseResponse and adaptative codebook vector to compute the filtered version */
/* in the Annex A, the filter being simpler, it's faster to directly filter the the vector using the weightedqLPCoefficients */
word16_t filteredAdaptativeCodebookVector[NB_LSP_COEFF+L_SUBFRAME]; /* in Q0, the first NB_LSP_COEFF words are set to zero and used by filter only */
memset(filteredAdaptativeCodebookVector, 0, NB_LSP_COEFF*sizeof(word16_t));
synthesisFilter(&(encoderChannelContext->excitationVector[L_PAST_EXCITATION + subframeIndex]), &(weightedqLPCoefficients[LPCoefficientsIndex]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]));
word64_t gainQuantizationXy, gainQuantizationYy; /* used to store in Q0 values reused in gain quantization */
word16_t adaptativeCodebookGain = computeAdaptativeCodebookGain(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), &gainQuantizationXy, &gainQuantizationYy); /* gain in Q14 */
adaptativeCodebookGain = computeAdaptativeCodebookGain(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), &gainQuantizationXy, &gainQuantizationYy); /* gain in Q14 */
/* increase parameters index and compute P0 if needed */
parametersIndex++;
@ -222,15 +230,11 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
}
/*** Fixed Codebook Search : compute the parameters for fixed codebook and the regular and convolved version of the fixed codebook vector ***/
word16_t fixedCodebookVector[L_SUBFRAME]; /* in Q13 */
word16_t convolvedFixedCodebookVector[L_SUBFRAME]; /* in Q12 */
fixedCodebookSearch(&(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(impulseResponseBuffer[NB_LSP_COEFF]), intPitchDelay, encoderChannelContext->lastQuantizedAdaptativeCodebookGain, &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), adaptativeCodebookGain,
&(parameters[parametersIndex]), &(parameters[parametersIndex+1]), fixedCodebookVector, convolvedFixedCodebookVector);
parametersIndex+=2;
/*** gains Quantization ***/
word16_t quantizedAdaptativeCodebookGain; /* in Q14 */
word16_t quantizedFixedCodebookGain; /* in Q1 */
gainQuantization(encoderChannelContext, &(encoderChannelContext->targetSignal[NB_LSP_COEFF]), &(filteredAdaptativeCodebookVector[NB_LSP_COEFF]), convolvedFixedCodebookVector, fixedCodebookVector, gainQuantizationXy, gainQuantizationYy,
&quantizedAdaptativeCodebookGain, &quantizedFixedCodebookGain, &(parameters[parametersIndex]), &(parameters[parametersIndex+1]));
parametersIndex+=2;


+ 25
- 14
src/findOpenLoopPitchDelay.c View File

@ -48,15 +48,28 @@ uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[])
/*** scale the signal to avoid overflows ***/
word16_t scaledWeightedInputSignalBuffer[MAXIMUM_INT_PITCH_DELAY+L_FRAME]; /* this buffer might store the scaled version of input Signal, if scaling is not needed, it is not used */
word16_t *scaledWeightedInputSignal; /* points to the begining of present frame either scaled or directly the input signal */
word64_t autocorrelation = 0;
uint16_t indexRange1=0, indexRange2=0, indexRange3Even=0, indexRange3;
word32_t correlationMaxRange1;
word32_t correlationMaxRange2;
word32_t correlationMaxRange3;
word32_t correlationMaxRange3Odd;
word32_t autoCorrelationRange1;
word32_t autoCorrelationRange2;
word32_t autoCorrelationRange3;
word32_t normalisedCorrelationMaxRange1;
word32_t normalisedCorrelationMaxRange2;
word32_t normalisedCorrelationMaxRange3;
uint16_t indexMultiple;
/* compute on 64 bits the autocorrelation on the input signal and if needed scale to have it on 32 bits */
word64_t autocorrelation = 0;
for (i=-MAXIMUM_INT_PITCH_DELAY; i<L_FRAME; i++) {
autocorrelation = MAC64(autocorrelation, weightedInputSignal[i], weightedInputSignal[i]);
}
if (autocorrelation>MAXINT32) {
int overflowScale;
scaledWeightedInputSignal = &(scaledWeightedInputSignalBuffer[MAXIMUM_INT_PITCH_DELAY]);
int overflowScale = PSHR(31-countLeadingZeros((word32_t)(autocorrelation>>31)),1); /* count number of bits needed over the 31 bits allowed and divide by 2 to get the right scaling for the signal */
overflowScale = PSHR(31-countLeadingZeros((word32_t)(autocorrelation>>31)),1); /* count number of bits needed over the 31 bits allowed and divide by 2 to get the right scaling for the signal */
for (i=-MAXIMUM_INT_PITCH_DELAY; i<L_FRAME; i++) {
scaledWeightedInputSignal[i] = SHR(weightedInputSignal[i], overflowScale);
}
@ -67,13 +80,11 @@ uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[])
/*** compute the correlationMax in the different ranges ***/
uint16_t indexRange1=0, indexRange2=0, indexRange3Even=0, indexRange3;
word32_t correlationMaxRange1 = getCorrelationMax(&indexRange1, scaledWeightedInputSignal, 20, 39, 1);
word32_t correlationMaxRange2 = getCorrelationMax(&indexRange2, scaledWeightedInputSignal, 40, 79, 1);
word32_t correlationMaxRange3 = getCorrelationMax(&indexRange3Even, scaledWeightedInputSignal, 80, 143, 2);
correlationMaxRange1 = getCorrelationMax(&indexRange1, scaledWeightedInputSignal, 20, 39, 1);
correlationMaxRange2 = getCorrelationMax(&indexRange2, scaledWeightedInputSignal, 40, 79, 1);
correlationMaxRange3 = getCorrelationMax(&indexRange3Even, scaledWeightedInputSignal, 80, 143, 2);
indexRange3 = indexRange3Even;
/* for the third range, correlationMax shall be computed at +1 and -1 around the maximum found as described in spec A3.4 */
word32_t correlationMaxRange3Odd;
if (indexRange3>80) { /* don't test value out of range [80, 143] */
correlationMaxRange3Odd = getCorrelation(scaledWeightedInputSignal, indexRange3-1);
if (correlationMaxRange3Odd>correlationMaxRange3) {
@ -88,9 +99,9 @@ uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[])
}
/*** normalise the correlations ***/
word32_t autoCorrelationRange1 = getCorrelation(&(scaledWeightedInputSignal[-indexRange1]), 0);
word32_t autoCorrelationRange2 = getCorrelation(&(scaledWeightedInputSignal[-indexRange2]), 0);
word32_t autoCorrelationRange3 = getCorrelation(&(scaledWeightedInputSignal[-indexRange3]), 0);
autoCorrelationRange1 = getCorrelation(&(scaledWeightedInputSignal[-indexRange1]), 0);
autoCorrelationRange2 = getCorrelation(&(scaledWeightedInputSignal[-indexRange2]), 0);
autoCorrelationRange3 = getCorrelation(&(scaledWeightedInputSignal[-indexRange3]), 0);
if (autoCorrelationRange1==0) {
autoCorrelationRange1 = 1; /* avoid division by 0 */
}
@ -102,15 +113,15 @@ uint16_t findOpenLoopPitchDelay(word16_t weightedInputSignal[])
}
/* according to ITU code comments, the normalisedCorrelationMax values fit on 16 bits when in Q0, so keep them in Q8 on 32 bits shall not give any overflow */
word32_t normalisedCorrelationMaxRange1 = MULT32_32_Q23(correlationMaxRange1, g729InvSqrt_Q0Q31(autoCorrelationRange1));
word32_t normalisedCorrelationMaxRange2 = MULT32_32_Q23(correlationMaxRange2, g729InvSqrt_Q0Q31(autoCorrelationRange2));
word32_t normalisedCorrelationMaxRange3 = MULT32_32_Q23(correlationMaxRange3, g729InvSqrt_Q0Q31(autoCorrelationRange3));
normalisedCorrelationMaxRange1 = MULT32_32_Q23(correlationMaxRange1, g729InvSqrt_Q0Q31(autoCorrelationRange1));
normalisedCorrelationMaxRange2 = MULT32_32_Q23(correlationMaxRange2, g729InvSqrt_Q0Q31(autoCorrelationRange2));
normalisedCorrelationMaxRange3 = MULT32_32_Q23(correlationMaxRange3, g729InvSqrt_Q0Q31(autoCorrelationRange3));
/*** Favouring the delays with the values in the lower range ***/
/* not clearly documented in spec A3.4, algo from the ITU code */
uint16_t indexMultiple = SHL(indexRange2,1); /* indexMultiple = 2*indexRange2 */
indexMultiple = SHL(indexRange2,1); /* indexMultiple = 2*indexRange2 */
if( abs(indexMultiple - indexRange3) < 5) { /* 2*indexRange2 - indexRange3 < 5 */
normalisedCorrelationMaxRange2 = ADD32(normalisedCorrelationMaxRange2, SHR(normalisedCorrelationMaxRange3,2)); /* Max2 += Max3*0.25 */
}


+ 26
- 23
src/fixedCodebookSearch.c View File

@ -53,8 +53,26 @@ void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], in
uint16_t *fixedCodebookParameter, uint16_t *fixedCodebookPulsesSigns, word16_t fixedCodebookVector[], word16_t fixedCodebookVectorConvolved[])
{
int i,j,n;
/* compute the target signal for fixed codebook spec 3.8.1 eq50 : fixedCodebookTargetSignal[i] = targetSignal[i] - (adaptativeCodebookGain * filteredAdaptativeCodebookVector[i]) */
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];
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<L_SUBFRAME; i++) {
fixedCodebookTargetSignal[i] = MSU16_16_Q14(targetSignal[i], filteredAdaptativeCodebookVector[i], adaptativeCodebookGain); /* adaptativeCodebookGain in Q14, other values in Q0 */
}
@ -65,22 +83,19 @@ void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], in
}
/* compute the correlation signal as in spec 3.8.1 eq52 */
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;
/* compute on 32 bits and get the maximum */
for (n=0; n<L_SUBFRAME; n++) {
correlationSignal32[n] = 0;
for (i=n; i<L_SUBFRAME; i++) {
correlationSignal32[n] = MAC16_16(correlationSignal32[n], fixedCodebookTargetSignal[i], impulseResponse[i-n]);
}
word32_t abscCrrelationSignal32 = correlationSignal32[n]>=0?correlationSignal32[n]:-correlationSignal32[n];
abscCrrelationSignal32 = correlationSignal32[n]>=0?correlationSignal32[n]:-correlationSignal32[n];
if (abscCrrelationSignal32>correlationSignalMax) {
correlationSignalMax = abscCrrelationSignal32;
}
}
/* normalise on 13 bits */
uint16_t correlationSignalMaxNorm = countLeadingZeros(correlationSignalMax);
correlationSignalMaxNorm = countLeadingZeros(correlationSignalMax);
if (correlationSignalMaxNorm<18) { /* if it doesn't already fit on 13 bits */
for (i=0; i<L_SUBFRAME; i++) {
correlationSignal[i] = (word16_t)(SHR(correlationSignal32[i], 18-correlationSignalMaxNorm));
@ -91,22 +106,9 @@ void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], in
}
}
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];
computeImpulseResponseCorrelationMatrix(impulseResponse, correlationSignal, correlationSignalSign, Phi);
/* search for impulses leading to a max in C^2/E : spec 3.8.1 eq53 */
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;
/* algorithm, not described in spec, retrieved from ITU code */
/* by tracks are intended series of index m0 track is 0,5,10,...35. m1 is 1,6,11,..,36. m2 is 2,7,12,..,37. m3 is 3,8,13,..,38. m4 is 4,9,14,..,39 */
/* note index m3 will follow track m3 and m4 */
@ -129,6 +131,7 @@ void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], in
for (i=0; i<2; i++) {
word16_t correlationM2 = -1;
int currentM2=0;
word32_t energyM2;
for (j=mSwitch[mIndex][0]; j<L_SUBFRAME; j+=5) { /* in the m2 range, find the correlation Max -> select m2 */
if (correlationSignal[j]>correlationM2 && j!=firstM2) {
currentM2 = j;
@ -137,7 +140,7 @@ void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], in
}
firstM2 = currentM2; /* to avoid selecting the same maximum at next iteration */
word32_t energyM2 = Phi[currentM2][currentM2]; /* compute the energy with terms of eq55 using m2 only: Phi'(m2,m2) */
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<L_SUBFRAME; j+=5) {
@ -308,17 +311,18 @@ void fixedCodebookSearch(word16_t targetSignal[], word16_t impulseResponse[], in
void computeImpulseResponseCorrelationMatrix(word16_t impulseResponse[], word16_t correlationSignal[], int correlationSignalSign[], word32_t Phi[L_SUBFRAME][L_SUBFRAME])
{
int i,j,iComp;
word32_t acc = 0;
uint16_t PhiScaling = 0;
int correlationSignalSignInv[L_SUBFRAME];
/* first compute the diagonal Phi(x,x) : Phi(39,39) = h[0]^2 # Phi(38,38) = Phi(39,39)+h[1]^2 */
/* this diagonal must be divided by 2 according to spec 3.8.1 eq57 */
word32_t acc = 0;
for (i=0, iComp=L_SUBFRAME-1; i<L_SUBFRAME; i++, iComp--) { /* i in [0..39], iComp in [39..0] */
acc = MAC16_16(acc, impulseResponse[i], impulseResponse[i]); /* impulseResponse in Q12 -> 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)*/
uint16_t PhiScaling = 0;
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<L_SUBFRAME; i++) {
@ -334,7 +338,6 @@ void computeImpulseResponseCorrelationMatrix(word16_t impulseResponse[], word16_
}
/* correlationSignal -> absolute value and get sign (and his inverse in an array) */
int correlationSignalSignInv[L_SUBFRAME];
for (i=0; i<L_SUBFRAME; i++) {
if (correlationSignal[i] >= 0) {
correlationSignalSign[i] = 1;


+ 24
- 18
src/gainQuantization.c View File

@ -57,10 +57,24 @@ void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext,
word16_t *quantizedAdaptativeCodebookGain, word16_t *quantizedFixedCodebookGain, uint16_t *gainCodebookStage1, uint16_t *gainCodebookStage2)
{
int i,j;
word64_t xz64=0, yz64=0, zz64=0;
word32_t xy;
word32_t yy;
word32_t xz;
word32_t yz;
word32_t zz;
uint16_t minNormalization = 31;
uint16_t currentNormalization;
word32_t bestAdaptativeCodebookGain, bestFixedCodebookGain;
word64_t denominator;
word16_t predictedFixedCodebookGain;
uint16_t indexBaseGa=0;
uint16_t indexBaseGb=0;
uint16_t indexGa=0, indexGb=0;
word64_t distanceMin = MAXINT64;
/*** compute spec 3.9 eq63 terms first on 64 bits and then scale them if needed to fit on 32 ***/
/* Xy64 and Yy64 already computed during adaptativeCodebookGain computation */
word64_t xz64=0, yz64=0, zz64=0;
for (i=0; i<L_SUBFRAME; i++) {
xz64 = MAC64(xz64, targetSignal[i], convolvedFixedCodebookVector[i]); /* in Q12 */
yz64 = MAC64(yz64, filteredAdaptativeCodebookVector[i], convolvedFixedCodebookVector[i]); /* in Q12 */
@ -68,14 +82,12 @@ void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext,
}
/* now scale this terms to have them fit on 32 bits - terms Xy, Xz and Yz shall fit on 31 bits because used in eq63 with a factor 2 */
word32_t xy = SHR64(((xy64<0)?-xy64:xy64),30);
word32_t yy = SHR64(yy64,31);
word32_t xz = SHR64(((xz64<0)?-xz64:xz64),30);
word32_t yz = SHR64(((yz64<0)?-yz64:yz64),30);
word32_t zz = SHR64(zz64,31);
xy = SHR64(((xy64<0)?-xy64:xy64),30);
yy = SHR64(yy64,31);
xz = SHR64(((xz64<0)?-xz64:xz64),30);
yz = SHR64(((yz64<0)?-yz64:yz64),30);
zz = SHR64(zz64,31);
uint16_t minNormalization = 31;
uint16_t currentNormalization;
currentNormalization = countLeadingZeros(xy);
if (currentNormalization<minNormalization) {
minNormalization = currentNormalization;
@ -118,20 +130,19 @@ void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext,
/* bestAdaptativeCodebookGain = (zz.xy - xz.yz) / (yy*zz) - yz^2) */
/* bestfixedCodebookGain = (yy*xz - xy*yz) / (yy*zz) - yz^2) */
/* best gain are computed in Q9 and Q2 and fits on 16 bits */
word32_t bestAdaptativeCodebookGain, bestFixedCodebookGain;
word64_t denominator = MAC64(MULT32_32(yy, zz), -yz, yz); /* (yy*zz) - yz^2) in Q24 (always >= 0)*/
denominator = MAC64(MULT32_32(yy, zz), -yz, yz); /* (yy*zz) - yz^2) in Q24 (always >= 0)*/
/* avoid division by zero */
if (denominator==0) { /* consider it to be one */
bestAdaptativeCodebookGain = (word32_t)(SHR64(MAC64(MULT32_32(zz, xy), -xz, yz), 15)); /* MAC in Q24 -> Q9 */
bestFixedCodebookGain = (word32_t)(SHR64(MAC64(MULT32_32(yy, xz), -xy, yz), 10)); /* MAC in Q12 -> Q2 */
} else {
/* bestAdaptativeCodebookGain in Q9 */
uint16_t numeratorNorm;
word64_t numerator = MAC64(MULT32_32(zz, xy), -xz, yz); /* in Q24 */
/* check if we can shift it by 9 without overflow as the bestAdaptativeCodebookGain in computed in Q9 */
word32_t numeratorH = (word32_t)(SHR64(numerator,32));
numeratorH = (numeratorH>0)?numeratorH:-numeratorH;
uint16_t numeratorNorm = countLeadingZeros(numeratorH);
numeratorNorm = countLeadingZeros(numeratorH);
if (numeratorNorm >= 9) {
bestAdaptativeCodebookGain = (word32_t)(DIV64(SHL64(numerator,9), denominator)); /* bestAdaptativeCodebookGain in Q9 */
} else {
@ -162,14 +173,11 @@ void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext,
}
/*** Compute the predicted gain as in spec 3.9.1 eq71 in Q6 ***/
word16_t predictedFixedCodebookGain = (word16_t)(SHR32(MACodeGainPrediction(encoderChannelContext->previousGainPredictionError, fixedCodebookVector), 12)); /* in Q16 -> Q4 range [3,1830] */
predictedFixedCodebookGain = (word16_t)(SHR32(MACodeGainPrediction(encoderChannelContext->previousGainPredictionError, fixedCodebookVector), 12)); /* in Q16 -> Q4 range [3,1830] */
/*** preselection spec 3.9.2 ***/
/* Note: spec just says to select the best 50% of each vector, ITU code go through magical constant computation to select the begining of a continuous range */
/* much more simple here : vector are ordened in growing order so just select 2 (4 for Gb) indexes before the first value to be superior to the best gain previously computed */
uint16_t indexBaseGa=0;
uint16_t indexBaseGb=0;
while (indexBaseGa<6 && bestFixedCodebookGain>(MULT16_16_Q14(GACodebook[indexBaseGa][1],predictedFixedCodebookGain))) { /* bestFixedCodebookGain> in Q2, GACodebook in Q12 *predictedFixedCodebookGain in Q4 -> Q16-14 */
indexBaseGa++;
}
@ -184,11 +192,9 @@ void gainQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext,
if (indexBaseGb>0) indexBaseGb--;
/*** test all possibilities of Ga and Gb indexes and select the best one ***/
uint16_t indexGa=0, indexGb=0;
xy = -SHL(xy,1); /* xy term is always used with a -2 factor */
xz = -SHL(xz,1); /* xz term is always used with a -2 factor */
yz = SHL(yz,1); /* yz term is always used with a 2 factor */
word64_t distanceMin = MAXINT64;
for (i=0; i<4; i++) {
for (j=0; j<8; j++) {


+ 32
- 26
src/postFilter.c View File

@ -58,12 +58,31 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
word16_t *postFilteredSignal)
{
int i,j;
word16_t LPGammaNCoefficients[NB_LSP_COEFF]; /* in Q12 */
word16_t *residualSignal;
word16_t *scaledResidualSignal;
word32_t correlationMax = (word32_t)MININT32;
int16_t intPitchDelayMax;
int16_t bestIntPitchDelay = 0;
word16_t *delayedResidualSignal;
word32_t residualSignalEnergy = 0; /* in Q-4 */
word32_t delayedResidualSignalEnergy = 0; /* in Q-4 */
word32_t maximumThree;
int16_t leadingZeros = 0;
word16_t correlationMaxWord16 = 0;
word16_t residualSignalEnergyWord16 = 0;
word16_t delayedResidualSignalEnergyWord16 = 0;
word16_t LPGammaDCoefficients[NB_LSP_COEFF]; /* in Q12 */
word16_t hf[22]; /* the truncated impulse response to short term filter Hf in Q12 */
word32_t rh1;
word16_t tiltCompensatedSignal[L_SUBFRAME]; /* in Q0 */
word16_t gainScalingFactor; /* in Q12 */
word32_t shortTermFilteredResidualSignalSquareSum = 0;
/********************************************************************/
/* Long Term Post Filter */
/********************************************************************/
/*** Compute LPGammaN and LPGammaD coefficients : LPGamma[0] = LP[0]*Gamma^(i+1) (i=0..9) ***/
word16_t LPGammaNCoefficients[NB_LSP_COEFF]; /* in Q12 */
/* GAMMA_XX constants are in Q15 */
LPGammaNCoefficients[0] = MULT16_16_P15(LPCoefficients[0], GAMMA_N1);
LPGammaNCoefficients[1] = MULT16_16_P15(LPCoefficients[1], GAMMA_N2);
@ -80,8 +99,8 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
/* Compute also a scaled residual signal: shift right by 2 to avoid overflows on 32 bits when computing correlation and energy */
/* pointers to current subframe beginning */
word16_t *residualSignal = &(decoderChannelContext->residualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]);
word16_t *scaledResidualSignal = &(decoderChannelContext->scaledResidualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]);
residualSignal = &(decoderChannelContext->residualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]);
scaledResidualSignal = &(decoderChannelContext->scaledResidualSignalBuffer[MAXIMUM_INT_PITCH_DELAY+subframeIndex]);
for (i=0; i<L_SUBFRAME; i++) {
word32_t acc = SHL((word32_t)reconstructedSpeech[i], 12); /* reconstructedSpeech in Q0 shifted to set acc in Q12 */
@ -94,10 +113,7 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
/*** Compute the maximum correlation on scaledResidualSignal delayed by intPitchDelay +/- 3 to get the best delay. Spec 4.2.1 eq80 ***/
/* using a scaled(Q-2) signals gives correlation in Q-4. */
word32_t correlationMax = (word32_t)MININT32;
int16_t intPitchDelayMax = intPitchDelay+3; /* intPitchDelayMax shall be < MAXIMUM_INT_PITCH_DELAY(143) */
int16_t bestIntPitchDelay = 0;
word16_t *delayedResidualSignal;
intPitchDelayMax = intPitchDelay+3; /* intPitchDelayMax shall be < MAXIMUM_INT_PITCH_DELAY(143) */
if (intPitchDelayMax>MAXIMUM_INT_PITCH_DELAY) {
intPitchDelayMax = MAXIMUM_INT_PITCH_DELAY;
}
@ -123,8 +139,6 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
}
/*** Compute the signal energy ∑r(n)*r(n) and delayed signal energy ∑rk(n)*rk(n) which shall be used to compute gl spec 4.2.1 eq81, eq 82 and eq83 ***/
word32_t residualSignalEnergy = 0; /* in Q-4 */
word32_t delayedResidualSignalEnergy = 0; /* in Q-4 */
delayedResidualSignal = &(scaledResidualSignal[-bestIntPitchDelay]); /* in Q-2, points to the residual signal delayed to give the higher correlation: rk(n) */
for (i=0; i<L_SUBFRAME; i++) {
residualSignalEnergy = MAC16_16(residualSignalEnergy, scaledResidualSignal[i], scaledResidualSignal[i]);
@ -135,7 +149,7 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
/* these variables must fit on 16bits for the following computation, to avoid loosing information, scale them */
/* at best fit: scale the higher of three to get the value over 2^14 and shift the other two from the same amount */
/* Note: all three value are >= 0 */
word32_t maximumThree = correlationMax;
maximumThree = correlationMax;
if (maximumThree<residualSignalEnergy) {
maximumThree = residualSignalEnergy;
}
@ -143,11 +157,6 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
maximumThree = delayedResidualSignalEnergy;
}
int16_t leadingZeros = 0;
word16_t correlationMaxWord16 = 0;
word16_t residualSignalEnergyWord16 = 0;
word16_t delayedResidualSignalEnergyWord16 = 0;
if (maximumThree>0) { /* if all of them a null, just do nothing otherwise shift right to get the max number in range [0x4000,0x8000[ */
leadingZeros = countLeadingZeros(maximumThree);
if (leadingZeros<16) {
@ -200,7 +209,6 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
/* compute hf the truncated (to 22 coefficients) impulse response of the filter A(z/γn)/A(z/γd) described in spec 4.2.2 eq84 */
/* hf(i) = LPGammaNCoeff[i] - ∑[j:0..9]LPGammaDCoeff[j]*hf[i-j-1]) */
word16_t LPGammaDCoefficients[NB_LSP_COEFF]; /* in Q12 */
/* GAMMA_XX constants are in Q15 */
LPGammaDCoefficients[0] = MULT16_16_P15(LPCoefficients[0], GAMMA_D1);
LPGammaDCoefficients[1] = MULT16_16_P15(LPCoefficients[1], GAMMA_D2);
@ -213,7 +221,6 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
LPGammaDCoefficients[8] = MULT16_16_P15(LPCoefficients[8], GAMMA_D9);
LPGammaDCoefficients[9] = MULT16_16_P15(LPCoefficients[9], GAMMA_D10);
word16_t hf[22]; /* the truncated impulse response to short term filter Hf in Q12 */
hf[0] = 4096; /* 1 in Q12 as LPGammaNCoefficients and LPGammaDCoefficient doesn't contain the first element which is 1 and past values of hf are 0 */
for (i=1; i<11; i++) {
word32_t acc = (word32_t)SHL(LPGammaNCoefficients[i-1],12); /* LPGammaNCoefficients in Q12 -> acc in Q24 */
@ -233,22 +240,22 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
/* hf is then used to compute k'1 spec 4.2.3 eq87: k'1 = -rh1/rh0 */
/* rh0 = ∑[i:0..21]hf[i]*hf[i] */
/* rh1 = ∑[i:0..20]hf[i]*hf[i+1] */
word32_t rh1 = MULT16_16(hf[0], hf[1]);
rh1 = MULT16_16(hf[0], hf[1]);
for (i=1; i<21; i++) {
rh1 = MAC16_16(rh1, hf[i], hf[i+1]); /* rh1 in Q24 */
}
/* tiltCompensationGain is set to 0 if k'1>0 -> rh1<0 (as rh0 is always>0) */
word16_t tiltCompensatedSignal[L_SUBFRAME]; /* in Q0 */
if (rh1<0) { /* tiltCompensationGain = 0 -> no gain filter is off, just copy the input */
memcpy(tiltCompensatedSignal, decoderChannelContext->longTermFilteredResidualSignal, L_SUBFRAME*sizeof(word16_t));
} else { /*compute tiltCompensationGain = k'1*γt */
word16_t tiltCompensationGain;
word32_t rh0 = MULT16_16(hf[0], hf[0]);
for (i=1; i<22; i++) {
rh0 = MAC16_16(rh0, hf[i], hf[i]); /* rh0 in Q24 */
}
rh1 = MULT16_32_Q15(GAMMA_T, rh1); /* GAMMA_T in Q15, rh1 in Q24*/
word16_t tiltCompensationGain = (word16_t)SATURATE((word32_t)(DIV32(rh1,PSHR(rh0,12))), MAXINT16); /* rh1 in Q24, PSHR(rh0,12) in Q12 -> tiltCompensationGain in Q12 */
tiltCompensationGain = (word16_t)SATURATE((word32_t)(DIV32(rh1,PSHR(rh0,12))), MAXINT16); /* rh1 in Q24, PSHR(rh0,12) in Q12 -> tiltCompensationGain in Q12 */
/* compute filter Ht (spec A.4.2.3 eqA14) = 1 + gain*z(-1) */
for (i=0; i<L_SUBFRAME; i++) {
@ -274,9 +281,7 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
/********************************************************************/
/*** compute G(gain scaling factor) according to eqA15 : G = Sqrt((∑s(n)^2)/∑sf(n)^2 ) ***/
word16_t gainScalingFactor; /* in Q12 */
/* compute ∑sf(n)^2 scale the signal shifting left by 2 to avoid overflow on 32 bits sum */
word32_t shortTermFilteredResidualSignalSquareSum = 0;
for (i=0; i<L_SUBFRAME; i++) {
shortTermFilteredResidualSignalSquareSum = MAC16_16_Q4(shortTermFilteredResidualSignalSquareSum, decoderChannelContext->shortTermFilteredResidualSignal[i], decoderChannelContext->shortTermFilteredResidualSignal[i]);
}
@ -289,7 +294,7 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
postFilteredSignal[i] = decoderChannelContext->shortTermFilteredResidualSignal[i];
}
} else { /* we can compute adaptativeGain and output signal */
word16_t currentAdaptativeGain;
/* compute ∑s(n)^2 scale the signal shifting left by 2 to avoid overflow on 32 bits sum */
word32_t reconstructedSpeechSquareSum = 0;
for (i=0; i<L_SUBFRAME; i++) {
@ -299,14 +304,15 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
if (reconstructedSpeechSquareSum==0) { /* numerator is null -> current gain is null */
gainScalingFactor = 0;
} else {
word32_t fractionResult; /* stores ∑s(n)^2)/∑sf(n)^2 */
word32_t scaledShortTermFilteredResidualSignalSquareSum;
/* Compute ∑s(n)^2)/∑sf(n)^2 result shall be in Q10 */
/* normalise the numerator on 32 bits */
word16_t numeratorShift = countLeadingZeros(reconstructedSpeechSquareSum);
reconstructedSpeechSquareSum = SHL(reconstructedSpeechSquareSum, numeratorShift); /* reconstructedSpeechSquareSum*2^numeratorShift */
/* normalise denominator to get the result directly in Q10 if possible */
word32_t fractionResult; /* stores ∑s(n)^2)/∑sf(n)^2 */
word32_t scaledShortTermFilteredResidualSignalSquareSum = VSHR32(shortTermFilteredResidualSignalSquareSum, 10-numeratorShift); /* shortTermFilteredResidualSignalSquareSum*2^(numeratorShift-10)*/
scaledShortTermFilteredResidualSignalSquareSum = VSHR32(shortTermFilteredResidualSignalSquareSum, 10-numeratorShift); /* shortTermFilteredResidualSignalSquareSum*2^(numeratorShift-10)*/
if (scaledShortTermFilteredResidualSignalSquareSum==0) {/* shift might have sent to zero the denominator */
fractionResult = DIV32(reconstructedSpeechSquareSum, shortTermFilteredResidualSignalSquareSum); /* result in QnumeratorShift */
@ -324,7 +330,7 @@ void postFilter(bcg729DecoderChannelContextStruct *decoderChannelContext, word16
/* Compute the signal according to eq89 (spec 4.2.4 and section A4.2.4) */
/* currentGain = 0.9*previousGain + 0.1*gainScalingFactor the 0.1 factor has already been integrated in the variable gainScalingFactor */
/* outputsignal = currentGain*shortTermFilteredResidualSignal */
word16_t currentAdaptativeGain = decoderChannelContext->previousAdaptativeGain;
currentAdaptativeGain = decoderChannelContext->previousAdaptativeGain;
for (i=0; i<L_SUBFRAME; i++) {
currentAdaptativeGain = ADD16(gainScalingFactor, MULT16_16_P15(currentAdaptativeGain, 29491)); /* 29492 = 0.9 in Q15, result in Q12 */
postFilteredSignal[i] = MULT16_16_Q12(currentAdaptativeGain, decoderChannelContext->shortTermFilteredResidualSignal[i]);


+ 3
- 1
src/utils.c View File

@ -174,6 +174,8 @@ word32_t MACodeGainPrediction(word16_t *previousGainPredictionError, word16_t *f
/* compute the sum of squares of fixedCodebookVector in Q26 */
int i;
word32_t fixedCodebookVectorSquaresSum = 0;
word32_t acc;
for (i=0; i<L_SUBFRAME; i++) {
if (fixedCodebookVector[i] != 0) { /* as most of the codebook vector is egal to 0, it worth checking it to avoid useless multiplications */
/* fixedCodebookVector in Q1.13 and final sum in range [4, 8.48] (4 values filled with abs values: 1,1,1.8 and 1.8 in the vector give max value of sum) */
@ -185,7 +187,7 @@ word32_t MACodeGainPrediction(word16_t *previousGainPredictionError, word16_t *f
/* compute E| - E as in eq71, result in Q16 */
/* acc = 124.2884 - 3.0103*log2(Sum) */
/* acc = 8145364[32 bits Q16] - 24660[16 bits Q2.13]*log2(Sum)[32 bits Q16] */
word32_t acc = MAC16_32_Q13(8145364, -24660, g729Log2_Q0Q16(fixedCodebookVectorSquaresSum)); /* acc in Q16 */
acc = MAC16_32_Q13(8145364, -24660, g729Log2_Q0Q16(fixedCodebookVectorSquaresSum)); /* acc in Q16 */
/* accumulate the MA prediction described in eq69 to the previous Sum, result will be in E~(m) + E| -E as used in eq71 */
/* acc in Q16->Q24, previousGainPredictionError in Q10 and MAPredictionCoefficients in Q0.14*/


Loading…
Cancel
Save