From 860c8544e8f4074937df27577f473b1d69092fcb Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 30 Aug 2013 17:29:42 +0200 Subject: [PATCH] Fix compilation for Windows Phone 8. --- include/bcg729/decoder.h | 12 ++++-- include/bcg729/encoder.h | 12 ++++-- include/g729FixedPointMath.h | 23 ++++++----- include/utils.h | 11 ++++- msbcg729/bcg729_dec.c | 48 ++++++++++++++++++---- msbcg729/bcg729_enc.c | 62 ++++++++++++++++++++++++----- src/LP2LSPConversion.c | 17 ++++---- src/LSPQuantization.c | 27 ++++++------- src/adaptativeCodebookSearch.c | 15 ++++--- src/computeAdaptativeCodebookGain.c | 4 +- src/computeLP.c | 17 ++++---- src/computeWeightedSpeech.c | 3 +- src/decodeAdaptativeCodeVector.c | 6 +-- src/decodeFixedCodeVector.c | 2 +- src/decodeGains.c | 12 ++++-- src/decodeLSP.c | 6 ++- src/decoder.c | 26 ++++++------ src/encoder.c | 36 +++++++++-------- src/findOpenLoopPitchDelay.c | 39 +++++++++++------- src/fixedCodebookSearch.c | 49 ++++++++++++----------- src/gainQuantization.c | 42 ++++++++++--------- src/postFilter.c | 58 +++++++++++++++------------ src/utils.c | 4 +- 23 files changed, 336 insertions(+), 195 deletions(-) diff --git a/include/bcg729/decoder.h b/include/bcg729/decoder.h index cae1fa2..7ebe87b 100644 --- a/include/bcg729/decoder.h +++ b/include/bcg729/decoder.h @@ -23,13 +23,19 @@ typedef struct bcg729DecoderChannelContextStruct_struct bcg729DecoderChannelContextStruct; #include +#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 */ diff --git a/include/bcg729/encoder.h b/include/bcg729/encoder.h index 5967903..d7f2dc2 100644 --- a/include/bcg729/encoder.h +++ b/include/bcg729/encoder.h @@ -23,13 +23,19 @@ #include 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 */ diff --git a/include/g729FixedPointMath.h b/include/g729FixedPointMath.h index 8778199..72ace47 100644 --- a/include/g729FixedPointMath.h +++ b/include/g729FixedPointMath.h @@ -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)); } diff --git a/include/utils.h b/include/utils.h index 29b4629..c4ace84 100644 --- a/include/utils.h +++ b/include/utils.h @@ -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; diff --git a/msbcg729/bcg729_dec.c b/msbcg729/bcg729_dec.c index cca1973..e441860 100644 --- a/msbcg729/bcg729_dec.c +++ b/msbcg729/bcg729_dec.c @@ -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) diff --git a/msbcg729/bcg729_enc.c b/msbcg729/bcg729_enc.c index 070e389..e298e8f 100644 --- a/msbcg729/bcg729_enc.c +++ b/msbcg729/bcg729_enc.c @@ -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"); diff --git a/src/LP2LSPConversion.c b/src/LP2LSPConversion.c index 0e17548..e42218c 100644 --- a/src/LP2LSPConversion.c +++ b/src/LP2LSPConversion.c @@ -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 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=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; iONE_POINT_2_IN_Q14) { diff --git a/src/computeLP.c b/src/computeLP.c index 9a94ac1..d636c2c 100644 --- a/src/computeLP.c +++ b/src/computeLP.c @@ -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; iMAXINT32) { 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) */ diff --git a/src/computeWeightedSpeech.c b/src/computeWeightedSpeech.c index b386ba1..d20ca45 100644 --- a/src/computeWeightedSpeech.c +++ b/src/computeWeightedSpeech.c @@ -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 weightedqLPLowPassCoefficients[0] = weightedqLPCoefficients[0] - 0.7 */ for (i=1; i 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; npreviousGainPredictionError[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 */ diff --git a/src/decodeLSP.c b/src/decodeLSP.c index 4450592..960ccf0 100644 --- a/src/decodeLSP.c +++ b/src/decodeLSP.c @@ -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; ilastqLSF[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; ilastqLSF[i],15); /* Q2.13 -> Q2.28 */ diff --git a/src/decoder.c b/src/decoder.c index b7f867c..48b245b 100644 --- a/src/decoder.c +++ b/src/decoder.c @@ -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; subframeIndexsignalCurrentFrame, 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; subframeIndexexcitationVector[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; diff --git a/src/findOpenLoopPitchDelay.c b/src/findOpenLoopPitchDelay.c index 5139802..a697eb3 100644 --- a/src/findOpenLoopPitchDelay.c +++ b/src/findOpenLoopPitchDelay.c @@ -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; iMAXINT32) { + 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; i80) { /* 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 */ } diff --git a/src/fixedCodebookSearch.c b/src/fixedCodebookSearch.c index e415bf9..81fbfec 100644 --- a/src/fixedCodebookSearch.c +++ b/src/fixedCodebookSearch.c @@ -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=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 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 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 absolute value and get sign (and his inverse in an array) */ - int correlationSignalSignInv[L_SUBFRAME]; for (i=0; i= 0) { correlationSignalSign[i] = 1; diff --git a/src/gainQuantization.c b/src/gainQuantization.c index 5976fc7..294a5d7 100644 --- a/src/gainQuantization.c +++ b/src/gainQuantization.c @@ -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= 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++) { diff --git a/src/postFilter.c b/src/postFilter.c index 72e8bec..df66cf3 100644 --- a/src/postFilter.c +++ b/src/postFilter.c @@ -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; iMAXIMUM_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= 0 */ - word32_t maximumThree = correlationMax; + maximumThree = correlationMax; if (maximumThree0) { /* 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; ishortTermFilteredResidualSignal[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 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; ishortTermFilteredResidualSignal[i]); diff --git a/src/utils.c b/src/utils.c index 81ca645..3d58864 100644 --- a/src/utils.c +++ b/src/utils.c @@ -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; iQ24, previousGainPredictionError in Q10 and MAPredictionCoefficients in Q0.14*/