Commit 843c130c authored by johan's avatar johan

Implement G729 AnnexB : VAD/DTX/CNG

- VAD algo is actually the variant described in G729 Appendix II
+ move headers to src files
parent 133ce9d9
SUBDIRS = bcg729
include_HEADERS= adaptativeCodebookSearch.h \
basicOperationsMacros.h \
codebooks.h \
codecParameters.h \
computeAdaptativeCodebookGain.h \
computeLP.h \
computeWeightedSpeech.h \
decodeAdaptativeCodeVector.h \
decodeFixedCodeVector.h \
decodeGains.h \
decodeLSP.h \
findOpenLoopPitchDelay.h \
fixedCodebookSearch.h \
fixedPointMacros.h \
floatingPointMacros.h \
g729FixedPointMath.h \
gainQuantization.h \
interpolateqLSP.h \
LP2LSPConversion.h \
LPSynthesisFilter.h \
LSPQuantization.h \
postFilter.h \
postProcessing.h \
preProcessing.h \
qLSP2LP.h \
typedef.h \
utils.h
EXTRA_DIST=$(include_HEADERS)
......@@ -51,8 +51,9 @@ BCG729_VISIBILITY void closeBcg729DecoderChannel(bcg729DecoderChannelContextStru
/* -(i) decoderChannelContext : the channel context data */
/* -(i) bitStream : 15 parameters on 80 bits */
/* -(i) frameErased: flag: true, frame has been erased */
/* -(i) SIDFrameFlag: flag: true, frame is a SID one */
/* -(o) signal : a decoded frame 80 samples (16 bits PCM) */
/* */
/*****************************************************************************/
BCG729_VISIBILITY 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, uint8_t SIDFrameFlag, int16_t signal[]);
#endif /* ifndef DECODER_H */
......@@ -31,11 +31,13 @@ typedef struct bcg729EncoderChannelContextStruct_struct bcg729EncoderChannelCont
/*****************************************************************************/
/* initBcg729EncoderChannel : create context structure and initialise it */
/* parameters: */
/* -(i) enanbleVAD : flag set to 1: VAD/DTX is enabled */
/* return value : */
/* - the encoder channel context data */
/* */
/*****************************************************************************/
BCG729_VISIBILITY bcg729EncoderChannelContextStruct *initBcg729EncoderChannel();
BCG729_VISIBILITY bcg729EncoderChannelContextStruct *initBcg729EncoderChannel(uint8_t enableVAD);
/*****************************************************************************/
/* closeBcg729EncoderChannel : free memory of context structure */
......@@ -51,8 +53,11 @@ BCG729_VISIBILITY void closeBcg729EncoderChannel(bcg729EncoderChannelContextStru
/* -(i) encoderChannelContext : context for this encoder channel */
/* -(i) inputFrame : 80 samples (16 bits PCM) */
/* -(o) bitStream : The 15 parameters for a frame on 80 bits */
/* on 80 bits (5 16bits words) */
/* on 80 bits (5 16bits words) for voice frame, 4 on 2 byte for */
/* noise frame, 0 for untransmitted frames */
/* -(o) bitStreamLength : actual length of output, may be 0, 2 or 10 */
/* if VAD/DTX is enabled */
/* */
/*****************************************************************************/
BCG729_VISIBILITY void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t inputFrame[], uint8_t bitStream[]);
BCG729_VISIBILITY void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t inputFrame[], uint8_t bitStream[], uint8_t *bitStreamLength);
#endif /* ifndef ENCODER_H */
......@@ -26,6 +26,7 @@
/* signal and bitstream frame size in byte */
#define SIGNAL_FRAME_SIZE 160
#define BITSTREAM_FRAME_SIZE 10
#define NOISE_BITSTREAM_FRAME_SIZE 2
/* decoder struct: context for decoder channel and concealment */
struct bcg729Decoder_struct {
......@@ -49,11 +50,13 @@ static void filter_process(MSFilter *f){
while((inputMessage=ms_queue_get(f->inputs[0]))) {
while(inputMessage->b_rptr<inputMessage->b_wptr) {
/* if remaining data in RTP payload have the size of a SID frame it must be one, see RFC3551 section 4.5.6 : any SID frame must be the last one of the RPT payload */
uint8_t SIDFrameFlag = ((inputMessage->b_wptr-inputMessage->b_rptr)==NOISE_BITSTREAM_FRAME_SIZE)?1:0;
outputMessage = allocb(SIGNAL_FRAME_SIZE,0);
mblk_meta_copy(inputMessage, outputMessage);
bcg729Decoder(obj->decoderChannelContext, inputMessage->b_rptr, 0, (int16_t *)(outputMessage->b_wptr));
bcg729Decoder(obj->decoderChannelContext, inputMessage->b_rptr, 0, SIDFrameFlag, (int16_t *)(outputMessage->b_wptr));
outputMessage->b_wptr+=SIGNAL_FRAME_SIZE;
inputMessage->b_rptr+=BITSTREAM_FRAME_SIZE;
inputMessage->b_rptr += (SIDFrameFlag==1)?NOISE_BITSTREAM_FRAME_SIZE:BITSTREAM_FRAME_SIZE;
ms_queue_put(f->outputs[0],outputMessage);
ms_concealer_inc_sample_time(obj->concealer,f->ticker->time,10, 1);
}
......@@ -62,7 +65,7 @@ static void filter_process(MSFilter *f){
if (ms_concealer_context_is_concealement_required(obj->concealer, f->ticker->time)) {
outputMessage = allocb(SIGNAL_FRAME_SIZE,0);
bcg729Decoder(obj->decoderChannelContext, NULL, 1, (int16_t *)(outputMessage->b_wptr));
bcg729Decoder(obj->decoderChannelContext, NULL, 1, 0, (int16_t *)(outputMessage->b_wptr));
outputMessage->b_wptr+=SIGNAL_FRAME_SIZE;
mblk_set_plc_flag(outputMessage, 1);
ms_queue_put(f->outputs[0],outputMessage);
......
......@@ -24,11 +24,12 @@
/*filter common method*/
struct bcg729Encoder_struct {
bcg729EncoderChannelContextStruct *encoderChannelContext;
bcg729EncoderChannelContextStruct *encoderChannelContext;
MSBufferizer *bufferizer;
unsigned char ptime;
unsigned char max_ptime;
uint32_t ts;
uint8_t enableVAD;
};
static void filter_init(MSFilter *f){
......@@ -37,12 +38,13 @@ static void filter_init(MSFilter *f){
obj = (struct bcg729Encoder_struct*) f->data;
obj->ptime=20;
obj->max_ptime=100;
obj->enableVAD=0;
}
static void filter_preprocess(MSFilter *f){
struct bcg729Encoder_struct* obj= (struct bcg729Encoder_struct*) f->data;
obj->encoderChannelContext = initBcg729EncoderChannel(); /* initialize bcg729 encoder, return context */
obj->encoderChannelContext = initBcg729EncoderChannel(obj->enableVAD); /* initialize bcg729 encoder, return context */
obj->bufferizer=ms_bufferizer_new();
}
......@@ -59,17 +61,23 @@ static void filter_process(MSFilter *f){
/* process ptimes ms of data : (ptime in ms)/1000->ptime is seconds * 8000(sample rate) * 2(byte per sample) */
while(ms_bufferizer_get_avail(obj->bufferizer)>=obj->ptime*16){
uint16_t totalPacketDataLength = 0;
uint8_t bitStreamLength = 0;
outputMessage = allocb(obj->ptime,0); /* output bitStream is 80 bits long * number of samples */
/* process buffer in 10 ms frames */
for (bufferIndex=0; bufferIndex<obj->ptime; bufferIndex+=10) {
/* RFC3551 section 4.5.6 we must end the RTP payload of G729 frames when transmitting a SID frame : bitStreamLength == 2 */
for (bufferIndex=0; (bufferIndex<obj->ptime) && (bitStreamLength!=2); bufferIndex+=10) {
ms_bufferizer_read(obj->bufferizer,inputBuffer,160);
bcg729Encoder(obj->encoderChannelContext, (int16_t *)inputBuffer, outputMessage->b_wptr);
outputMessage->b_wptr+=10;
bcg729Encoder(obj->encoderChannelContext, (int16_t *)inputBuffer, outputMessage->b_wptr, &bitStreamLength);
outputMessage->b_wptr+=bitStreamLength;
totalPacketDataLength+=bitStreamLength;
}
obj->ts+=bufferIndex*8;
/* do not enqueue the message if no data out (DTX untransmitted frames) */
if (totalPacketDataLength>0) {
mblk_set_timestamp_info(outputMessage,obj->ts);
ms_queue_put(f->outputs[0],outputMessage);
}
obj->ts+=obj->ptime*8;
mblk_set_timestamp_info(outputMessage,obj->ts);
ms_queue_put(f->outputs[0],outputMessage);
}
}
......@@ -110,7 +118,14 @@ static int filter_add_fmtp(MSFilter *f, void *arg){
}
ms_message("MSBCG729Enc: got ptime=%i",obj->ptime);
} else if (fmtp_get_value(fmtp,"annexb",buf,sizeof(buf))){
if (strncmp(buf, "yes",3)) {
obj->enableVAD = 1;
ms_message("MSBCG729Enc: enable VAD/DTX - AnnexB");
}
}
/* parse annexB param here */
return 0;
}
......
......@@ -44,6 +44,9 @@ set(BCG729_SOURCE_FILES
preProcessing.c
qLSP2LP.c
utils.c
cng.c
dtx.c
vad.c
)
add_library(bcg729 SHARED ${BCG729_SOURCE_FILES})
......
......@@ -3,17 +3,17 @@
Copyright (C) 2011 Belledonne Communications, Grenoble, France
Author : Johan Pascal
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
......
This diff is collapsed.
......@@ -33,4 +33,16 @@ void initLSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContex
/* */
/*****************************************************************************/
void LSPQuantization(bcg729EncoderChannelContextStruct *encoderChannelContext, word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint16_t parameters[]);
/**********************************************************************************/
/* noiseLSPQuantization : Convert LSP to LSF, Quantize LSF and find L parameters, */
/* qLSF->qLSP as described in spec A3.2.4 */
/* parameters: */
/* -(i/o) previousqLSF : 4 previousqLSF, is updated by this function */
/* -(i) LSPCoefficients : 10 LSP coefficients in Q15 */
/* -(o) qLSPCoefficients : 10 qLSP coefficients in Q15 */
/* -(o) parameters : 3 parameters L0, L1, L2 */
/* */
/**********************************************************************************/
void noiseLSPQuantization(word16_t previousqLSF[MA_MAX_K][NB_LSP_COEFF], word16_t LSPCoefficients[], word16_t qLSPCoefficients[], uint8_t parameters[]);
#endif /* LSPQUANTIZATION_H */
......@@ -26,7 +26,10 @@ libbcg729_la_SOURCES= LP2LSPConversion.c \
postProcessing.c \
preProcessing.c \
qLSP2LP.c \
utils.c
utils.c \
cng.c \
vad.c \
dtx.c
libbcg729_la_LDFLAGS= -no-undefined
......
This diff is collapsed.
/*
cng.h
Copyright (C) 2011 Belledonne Communications, Grenoble, France
Author : Johan Pascal
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef CNG_H
#define CNG_H
/*****************************************************************************/
/* initBcg729CNGChannel : create context structure and initialise it */
/* return value : */
/* - the CNG channel context data */
/* */
/*****************************************************************************/
bcg729CNGChannelContextStruct *initBcg729CNGChannel();
void computeComfortNoiseExcitationVector(word16_t targetGain, uint16_t *randomGeneratorSeed, word16_t *excitationVector);
/*******************************************************************************************/
/* decodeSIDframe : as is spec B4.4 and B4.5 */
/* first check if we have a SID frame or a missing/untransmitted frame */
/* for SID frame get paremeters(gain and LSP) */
/* Then generate excitation vector and update qLSP */
/* parameters: */
/* -(i/o):CNGChannelContext : context containing all informations needed for CNG */
/* -(i): previousFrameIsActiveFlag: true if last decoded frame was an active one */
/* -(i): bitStream: for SID frame contains received params as in spec B4.3, */
/* NULL for missing/untransmitted frame */
/* -(i/o): excitationVector in Q0, accessed in range [-L_PAST_EXCITATION,L_FRAME-1] */
/* [-154,79] */
/* -(i/o): previousqLSP : previous quantised LSP in Q0.15 (NB_LSP_COEFF values) */
/* -(o): LP: 20 LP coefficients in Q12 */
/* -(i/o): pseudoRandomSeed : seed used in the pseudo random number generator */
/* -(i/o): previousLCodeWord: in Q2.13, buffer to store the last 4 frames codewords, */
/* used to compute the current qLSF */
/* */
/*******************************************************************************************/
void decodeSIDframe(bcg729CNGChannelContextStruct *CNGChannelContext, uint8_t previousFrameIsActiveFlag, uint8_t *bitStream, word16_t *excitationVector, word16_t *previousqLSP, word16_t *LP, uint16_t *pseudoRandomSeed, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF]);
#endif /* ifndef CNG_H */
......@@ -191,6 +191,12 @@ word16_t L2L3[L2_RANGE][NB_LSP_COEFF] = { /* The second stage is a 10-bit VQ spl
{ -163, 674, -11, -886, 531, -1125, -265, -242, 724, 934}
};
/* index used by CNG to reach a subset of L1, L2 and L3 codebooks */
uint8_t L1SubsetIndex[32] = {96,52,20,54,86,114,82,68,36,121,48,92,18,120,
94,124,50,125,4,100,28,76,12,117,81,22,90,116,
127,21,108,66};
uint8_t L2SubsetIndex[16] = {31,21,9,3,10,2,19,26,4,3,11,29,15,27,21,12};
uint8_t L3SubsetIndex[16] = {16,1,0,0,8,25,22,20,19,23,20,31,4,31,20,31};
word16_t MAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF] = { /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
{
......@@ -217,6 +223,35 @@ word16_t invMAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1/(1 - Sum(MAPredictor)
{ 9202, 7320, 6788, 7738, 8170, 8154, 8856, 8818, 8366, 8544}
};
/* DTX/CNG use different values for MA predictor */
word16_t noiseMAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF] = { /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
{
{ 8421, 9109, 9175, 8965, 9034, 9057, 8765, 8775, 9106, 8673},
{ 7018, 7189, 7638, 7307, 7444, 7379, 7038, 6956, 6930, 6868},
{ 5472, 4990, 5134, 5177, 5246, 5141, 5206, 5095, 4830, 5147},
{ 4056, 3031, 2614, 3024, 2916, 2713, 3309, 3237, 2857, 3473}
},
{
{ 8145, 8617, 8779, 8648, 8718, 8829, 8713, 8705, 8806, 8231 },
{ 5894, 5525, 5603, 5773, 6016, 5968, 5896, 5835, 5721, 5707 },
{ 4568, 3765, 3605, 3963, 4144, 4038, 4225, 4139, 3914, 4255 },
{ 3643, 2455, 1944, 2466, 2438, 2259, 2798, 2775, 2479, 3124 }
}
};
word16_t noiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1 - Sum(MAPredictor) in Q0.15 */
{ 7798, 8447, 8205, 8293, 8126, 8477, 8447, 8703, 9043, 8604},
{10514, 12402, 12833, 11914, 11447, 11670, 11132, 11311, 11844, 11447}
};
word16_t invNoiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF] = {/* 1/(1 - Sum(MAPredictor)) in Q3.12 */
{17210, 15888, 16357, 16183, 16516, 15833, 15888, 15421, 14840, 15597},
{12764, 10821, 10458, 11264, 11724, 11500, 12056, 11865, 11331, 11724}
};
/* codebook for adaptative code vector */
word16_t b30[31] = { /* in Q0.15 */
29443, 25207, 14701, 3143, -4402, -5850, -2783, 1211, 3130, 2259, 0, -1652, -1666, -464, 756, 1099, 550, -245, -634, -451, 0, 308, 296, 78, -120, -165, -79, 34, 91, 70, 0};
......@@ -291,6 +326,31 @@ word16_t wlp[L_LP_ANALYSIS_WINDOW] = { /* in Q15 */
23055, 22117, 21145, 20139, 19102, 18036, 16941, 15820, 14674, 13505,
12315, 11106, 9879, 8637, 7381, 6114, 4838, 3554, 2264, 971};
/* lag window as defined in spec 3.2.1 eq6 */
word16_t wlag[NB_LSP_COEFF+1] = { /* in Q15 note first coeff is not used */
32767, 32728, 32619, 32438, 32187, 31867, 31480, 31029, 30517, 29946, 29321};
/* lag window as defined in spec 3.2.1 eq6 : up to 12 values for VAD */
/* wlag[0] = 1.00000000 not used
wlag[1] = 0.99879038
wlag[2] = 0.99546897
wlag[3] = 0.98995781
wlag[4] = 0.98229337
wlag[5] = 0.97252619
wlag[6] = 0.96072036
wlag[7] = 0.94695264
wlag[8] = 0.93131179
wlag[9] = 0.91389757
wlag[10]= 0.89481968
wlag[11]= 0.87419660
wlag[12]= 0.85215437
*/
word16_t wlag[NB_LSP_COEFF+3] = { /* in Q15 note first coeff is not used */
32767, 32728, 32619, 32438, 32187, 31867, 31480, 31029, 30517, 29946, 29321, 28646, 27923};
/* quantised SID gain retrieved from ITU code, in Q3 */
word16_t SIDGainCodebook[32] = {
2, 5, 8, 13, 20, 32, 50, 64,
80, 101, 127, 160, 201, 253, 318, 401,
505, 635, 800, 1007, 1268, 1596, 2010, 2530,
3185, 4009, 5048, 6355, 8000,10071,12679,15962 };
/* Low Band Filter FIR for VAD in Q15 */
word16_t lowBandFilter[NB_LSP_COEFF+3] = {7869, 7011, 4838, 2299, 321, -660, -782, -484, -164, 3, 39, 21, 4};
......@@ -31,6 +31,10 @@ extern word16_t L2L3[L2_RANGE][NB_LSP_COEFF]; /* Doc : The second stage is a 10-
extern word16_t MAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF]; /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
extern word16_t MAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1 - Sum(MAPredictor) in Q0.15 */
extern word16_t invMAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1/(1 - Sum(MAPredictor)) in Q3.12 */
/* same as above but used for SID frame */
extern word16_t noiseMAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF]; /* the MA predictor coefficients in Q0.15 but max value < 0.5 so it fits on 15 bits */
extern word16_t noiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1 - Sum(MAPredictor) in Q0.15 */
extern word16_t invNoiseMAPredictorSum[L0_RANGE][NB_LSP_COEFF]; /* 1/(1 - Sum(MAPredictor)) in Q3.12 */
/* codebook for adaptative code vector */
extern word16_t b30[31];
......@@ -43,6 +47,13 @@ extern uint16_t indexMappingGB[16];
extern word16_t GACodebook[8][2];
extern word16_t GBCodebook[16][2];
extern word16_t MAPredictionCoefficients[4];
extern word16_t SIDGainCodebook[32];
extern uint8_t L1SubsetIndex[32];
extern uint8_t L2SubsetIndex[16];
extern uint8_t L3SubsetIndex[16];
/* codebook for VAD */
extern word16_t lowBandFilter[NB_LSP_COEFF+3];
/* codebook for LP Analysis */
extern word16_t wlp[L_LP_ANALYSIS_WINDOW];
......
......@@ -37,6 +37,9 @@
#define L1_RANGE (1<<L1_LENGTH)
#define L2_RANGE (1<<L2_LENGTH)
#define L3_RANGE (1<<L3_LENGTH)
/* SID frame use a subset of L1 and L2 */
#define NOISE_L1_RANGE 32
#define NOISE_L2_RANGE 16
/* MA Prediction history length: maximum number of previous LSP used */
#define MA_MAX_K 4
......@@ -110,4 +113,26 @@
/*** LP to LSP conversion ***/
#define NB_COMPUTED_VALUES_CHEBYSHEV_POLYNOMIAL 51
/*** CNG ***/
/* 1/2sqrt*(40) in Q1.13 */
#define GAUSSIAN_EXCITATION_COEFF_FACTOR 25905
/* 0.75 in Q15 */
#define COEFF_K 24576
/*** VAD ***/
#define LOG2_240_Q16 518186
#define INV_LOG2_10_Q15 9864
/* buffer size for history on different values (defined in spec table B.1)*/
#define Ni 32
#define N0 128
/*** DTX ***/
/* 1.12202 in Q20 */
#define THRESHOLD3_IN_Q20 1176553
/* 1.20226 in Q20 */
#define THRESHOLD1_IN_Q20 1260661
#define CNG_DTX_RANDOM_SEED_INIT 11111
#endif /* ifndef CODECPARAMETERS_H */
This diff is collapsed.
......@@ -20,13 +20,30 @@
*/
#ifndef COMPUTELP_H
#define COMPUTELP_H
/*****************************************************************************/
/* autoCorrelation2LP: convert autocorrelation coefficients to LP using */
/* Levinson-Durbin algo described in spec 3.2.2 */
/* parameters : */
/* -(i) autoCorrelationCoefficients : 11 values in variable scale */
/* scale is not needed here as a division cancel it */
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
/* -(o) reflectionCoefficient: in Q31, k[1] generated during Levinson */
/* Durbin LP coefficient generation and needed for VAD */
/* -(o) residualEnergy : with the same scale factor as input */
/* autoCorrelationCoefficients, needed by DTX */
/* */
/*****************************************************************************/
void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoefficientsQ12[], word32_t *reflectionCoefficient, word32_t *residualEnergy);
/*****************************************************************************/
/* computeLP : As described in spec 3.2.1 and 3.2.2 : Windowing, */
/* Autocorrelation and Levinson-Durbin algorithm */
/* parameters: */
/* -(i) signal: 240 samples in Q0, the last 40 are from next frame */
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
/* -(o) reflectionCoefficient: in Q31, k[1] generated during Levinson */
/* Durbin LP coefficient generation and needed for VAD */
/* */
/*****************************************************************************/
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[]);
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t *reflectionCoefficient, word32_t autoCorrelationCoefficients[], word32_t noLagAutocorrelationCoefficients[], int8_t *autoCorrelationCoefficientsScale, uint8_t autoCorrelationCoefficientsNumber);
#endif /* ifndef COMPUTELP_H */
......@@ -33,6 +33,53 @@ void initDecodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderCh
}
/*****************************************************************************/
/* computeAdaptativeCodeVector : as in spec 4.1.3 */
/* parameters: */
/* -(i/o) excitationVector : in Q0 excitation accessed from */
/* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */
/* and [0, L_SUBFRAME[ as output to store the adaptative */
/* codebook vector */
/* -(i/o) fracPitchDelay : the fractionnal part of Pitch Delay. */
/* -(i/o) intPitchDelay : the integer part of Pitch Delay. */
/* */
/*****************************************************************************/
void computeAdaptativeCodebookVector(word16_t *excitationVector, int16_t fracPitchDelay, int16_t intPitchDelay) {
word16_t *excitationVectorMinusK; /* pointer to u(-k) */
int n;
/* compute the adaptative codebook vector using the pitch delay and the past excitation vector */
/* from spec 4.1.3 and 3.7.1 */
/* shall compute v(n ) = ∑ u (n - k + i )b30 (t + 3i ) + ∑ u (n - k + 1 + i )b30 (3 - t + 3i ) for i=0,...,9 and n = 0,...,39 (t in 0, 1, 2) */
/* with k = intPitchDelay and t = fracPitchDelay wich must be converted from range -1,0,1 to 0,1,2 */
/* u the past excitation vector */
/* v the adaptative codebook vector */
/* b30 an interpolation filter */
/* 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 */
fracPitchDelay = 2;
} else {
fracPitchDelay = -fracPitchDelay; /* 0 unchanged, -1 -> +1 */
excitationVectorMinusK = &(excitationVector[-intPitchDelay]); /* -(k-1/3) -> -k+1/3 or -(k) -> -k*/
}
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 */
word16_t *b301 = &(b30[fracPitchDelay]); /* point to b30(t) in Q0.15 : sums of all b30 coeffs is < 2, no overflow possible on 32 bits */
word16_t *b302 = &(b30[3-fracPitchDelay]); /* point to b30(3-t) in Q0.15*/
int i,j; /* j will store 3i */
word32_t acc = 0; /* in Q15 */
for (i=0, j=0; i<10; i++, j+=3) {
acc = MAC16_16(acc, excitationVectorNMinusK[-i], b301[j]); /* Note : the spec says: u(n−k+i)b30(t+3i) but the ITU code do (and here too) u(n-k-i )b30(t+3i) */
acc = MAC16_16(acc, excitationVectorNMinusKPlusOne[i], b302[j]); /* u(n-k+1+i)b30(3-t+3i) */
}
excitationVector[n] = SATURATE(PSHR(acc, 15), MAXINT16); /* acc in Q15, shift/round to unscaled value and check overflow on 16 bits */
}
}
/*****************************************************************************/
/* decodeAdaptativeCodeVector : as in spec 4.1.3 */
......@@ -55,8 +102,6 @@ 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 */
......@@ -108,38 +153,9 @@ void decodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChanne
}
}
/* compute the adaptative codebook vector using the pitch delay we just get and the past excitation vector */
computeAdaptativeCodebookVector(excitationVector, fracPitchDelay, *intPitchDelay);
/* now compute the adaptative codebook vector using the pitch delay we just get and the past excitation vector */
/* from spec 4.1.3 and 3.7.1 */
/* shall compute v(n ) = ∑ u (n - k + i )b30 (t + 3i ) + ∑ u (n - k + 1 + i )b30 (3 - t + 3i ) for i=0,...,9 and n = 0,...,39 (t in 0, 1, 2) */
/* with k = intPitchDelay and t = fracPitchDelay wich must be converted from range -1,0,1 to 0,1,2 */
/* u the past excitation vector */
/* v the adaptative codebook vector */
/* b30 an interpolation filter */
/* 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 */
fracPitchDelay = 2;
} else {
fracPitchDelay = -fracPitchDelay; /* 0 unchanged, -1 -> +1 */
excitationVectorMinusK = &(excitationVector[-(*intPitchDelay)]); /* -(k-1/3) -> -k+1/3 or -(k) -> -k*/
}
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 */
word16_t *b301 = &(b30[fracPitchDelay]); /* point to b30(t) in Q0.15 : sums of all b30 coeffs is < 2, no overflow possible on 32 bits */
word16_t *b302 = &(b30[3-fracPitchDelay]); /* point to b30(3-t) in Q0.15*/
int i,j; /* j will store 3i */
word32_t acc = 0; /* in Q15 */
for (i=0, j=0; i<10; i++, j+=3) {
acc = MAC16_16(acc, excitationVectorNMinusK[-i], b301[j]); /* Note : the spec says: u(n−k+i)b30(t+3i) but the ITU code do (and here too) u(n-k-i )b30(t+3i) */
acc = MAC16_16(acc, excitationVectorNMinusKPlusOne[i], b302[j]); /* u(n-k+1+i)b30(3-t+3i) */
}
excitationVector[n] = SATURATE(PSHR(acc, 15), MAXINT16); /* acc in Q15, shift/round to unscaled value and check overflow on 16 bits */
}
return;
}
......@@ -23,6 +23,19 @@
/* init function */
void initDecodeAdaptativeCodeVector(bcg729DecoderChannelContextStruct *decoderChannelContext);
/*****************************************************************************/
/* computeAdaptativeCodeVector : as in spec 4.1.3 */
/* parameters: */
/* -(i/o) excitationVector : in Q0 excitation accessed from */
/* [-MAXIMUM_INT_PITCH_DELAY(143), -1] as input */
/* and [0, L_SUBFRAME[ as output to store the adaptative */
/* codebook vector */
/* -(i/o) fracPitchDelay : the fractionnal part of Pitch Delay. */
/* -(i/o) intPitchDelay : the integer part of Pitch Delay. */
/* */
/*****************************************************************************/
void computeAdaptativeCodebookVector(word16_t *excitationVector, int16_t fracPitchDelay, int16_t intPitchDelay);
/*****************************************************************************/
/* decodeAdaptativeCodeVector : as in spec 4.1.3 */
/* parameters: */
......
......@@ -48,6 +48,70 @@ void initDecodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext)
}
}
//[MA_MAX_K][NB_LSP_COEFF]; /* in Q2.13, buffer to store the last 4 frames codewords, used to compute the current qLSF */
/*****************************************************************************/
/* computeqLSF : get qLSF extracted from codebooks and process them */
/* according to spec 3.2.4 */
/* parameters: */
/* -(i/o) codebookqLSF : 10 values i Q2.13 to be updated */
/* -(i/o) previousCodeWord : codewords for the last 4 subframes in Q2.13*/
/* is updated by this function */
/* -(i) L0: the Switched MA predictor retrieved from bitstream */
/* */
/*****************************************************************************/
void computeqLSF(word16_t *codebookqLSF, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF], uint8_t L0, word16_t currentMAPredictor[L0_RANGE][MA_MAX_K][NB_LSP_COEFF], word16_t currentMAPredictorSum[L0_RANGE][NB_LSP_COEFF]) {
int i,j;
word32_t acc; /* Accumulator in Q2.28 */
/*** rearrange in order to have a minimum distance between two consecutives coefficients ***/
rearrangeCoefficients(codebookqLSF, GAP1);
rearrangeCoefficients(codebookqLSF, GAP2); /* codebookqLSF still in Q2.13 */
/*** doc 3.2.4 eq(20) ***/
/* compute the qLSF as a weighted sum(weighted by MA coefficient selected according to L0 value) of previous and current frame L codewords coefficients */
/* L0 is the Switched MA predictor of LSP quantizer(1 bit) */
/* codebookqLSF 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 */
for (i=0; i<NB_LSP_COEFF; i++) {
acc = MULT16_16(currentMAPredictorSum[L0][i], codebookqLSF[i]);
for (j=MA_MAX_K-1; j>=0; j--) {
acc = MAC16_16(acc, currentMAPredictor[L0][j][i], previousLCodeWord[j][i]);
previousLCodeWord[j][i] = (j>0)?previousLCodeWord[j-1][i]:codebookqLSF[i]; /* update the previousqLCodeWord array: row[0] = current code word and row[j]=row[j-1] */
}
/* acc in Q2.28, shift back the acc to a Q2.13 with rounding */
codebookqLSF[i] = (word16_t)PSHR(acc, 15); /* codebookqLSF in Q2.13 */
}
/* Note : codebookqLSF buffer now contains qLSF */
/*** doc 3.2.4 qLSF stability ***/
/* qLSF in Q2.13 as are qLSF_MIN and qLSF_MAX and MIN_qLSF_DISTANCE */
/* sort the codebookqLSF array */
insertionSort(codebookqLSF, NB_LSP_COEFF);
/* check for low limit on qLSF[0] */
if (codebookqLSF[1]<qLSF_MIN) {
codebookqLSF[1] = qLSF_MIN;
}
/* check and rectify minimum distance between two consecutive qLSF */
for (i=0; i<NB_LSP_COEFF-1; i++) {
if (SUB16(codebookqLSF[i+1],codebookqLSF[i])<MIN_qLSF_DISTANCE) {
codebookqLSF[i+1] = codebookqLSF[i]+MIN_qLSF_DISTANCE;
}
}
/* check for upper limit on qLSF[NB_LSP_COEFF-1] */
if (codebookqLSF[NB_LSP_COEFF-1]>qLSF_MAX) {
codebookqLSF[NB_LSP_COEFF-1] = qLSF_MAX;
}
}
/*****************************************************************************/
/* decodeLSP : decode LSP coefficients as in spec 4.1.1/3.2.4 */
/* parameters: */
......@@ -65,7 +129,6 @@ 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 */
......@@ -81,51 +144,7 @@ void decodeLSP(bcg729DecoderChannelContextStruct *decoderChannelContext, uint16_
currentqLSF[i] = ADD16(L1[L[1]][i], L2L3[L[3]][i]); /* same as previous, output in Q2.13 */
}
/*** rearrange in order to have a minimum distance between two consecutives coefficients ***/
rearrangeCoefficients(currentqLSF, GAP1);
rearrangeCoefficients(currentqLSF, GAP2); /* currentqLSF still in Q2.13 */
/*** doc 3.2.4 eq(20) ***/
/* compute the qLSF as a weighted sum(weighted by MA coefficient selected according to L0 value) of previous and current frame L codewords coefficients */
/* L[0] is the Switched MA predictor of LSP quantizer(1 bit) */
/* 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 */