Commit 948d32ad authored by johan's avatar johan

Add support for RFC3389 Comfort Noise Payload

parent 52e10238
......@@ -50,10 +50,12 @@ BCG729_VISIBILITY void closeBcg729DecoderChannel(bcg729DecoderChannelContextStru
/* parameters: */
/* -(i) decoderChannelContext : the channel context data */
/* -(i) bitStream : 15 parameters on 80 bits */
/* -(i): bitStreamLength : in bytes, length of previous buffer */
/* -(i) frameErased: flag: true, frame has been erased */
/* -(i) SIDFrameFlag: flag: true, frame is a SID one */
/* -(i) rfc3389PayloadFlag: true when CN payload follow rfc3389 */
/* -(o) signal : a decoded frame 80 samples (16 bits PCM) */
/* */
/*****************************************************************************/
BCG729_VISIBILITY void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t frameErasureFlag, uint8_t SIDFrameFlag, int16_t signal[]);
BCG729_VISIBILITY void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t bitStreamLength, uint8_t frameErasureFlag, uint8_t SIDFrameFlag, uint8_t rfc3389PayloadFlag, int16_t signal[]);
#endif /* ifndef DECODER_H */
......@@ -60,4 +60,16 @@ BCG729_VISIBILITY void closeBcg729EncoderChannel(bcg729EncoderChannelContextStru
/* */
/*****************************************************************************/
BCG729_VISIBILITY void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int16_t inputFrame[], uint8_t bitStream[], uint8_t *bitStreamLength);
/*****************************************************************************/
/* bcg729GetRFC3389Payload : return the comfort noise payload according to */
/* RFC3389 for the last CN frame generated by encoder */
/* */
/* parameters: */
/* -(i) encoderChannelContext : retrieve the last CN frame encoded */
/* using this context */
/* -(o) payload : 11 parameters following RFC3389 with filter order 10 */
/* */
/*****************************************************************************/
BCG729_VISIBILITY void bcg729GetRFC3389Payload(bcg729EncoderChannelContextStruct *encoderChannelContext, uint8_t payload[]);
#endif /* ifndef ENCODER_H */
......@@ -30,7 +30,7 @@
/* decoder struct: context for decoder channel and concealment */
struct bcg729Decoder_struct {
bcg729DecoderChannelContextStruct *decoderChannelContext;
bcg729DecoderChannelContextStruct *decoderChannelContext;
MSConcealerContext *concealer;
};
......@@ -54,7 +54,7 @@ static void filter_process(MSFilter *f){
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, SIDFrameFlag, (int16_t *)(outputMessage->b_wptr));
bcg729Decoder(obj->decoderChannelContext, inputMessage->b_rptr, (SIDFrameFlag==1)?NOISE_BITSTREAM_FRAME_SIZE:BITSTREAM_FRAME_SIZE, 0, SIDFrameFlag, 0, (int16_t *)(outputMessage->b_wptr));
outputMessage->b_wptr+=SIGNAL_FRAME_SIZE;
inputMessage->b_rptr += (SIDFrameFlag==1)?NOISE_BITSTREAM_FRAME_SIZE:BITSTREAM_FRAME_SIZE;
ms_queue_put(f->outputs[0],outputMessage);
......@@ -65,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, 0, (int16_t *)(outputMessage->b_wptr));
bcg729Decoder(obj->decoderChannelContext, NULL, 0, 1, 0, 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);
......
......@@ -34,6 +34,7 @@
#include "qLSP2LP.h"
#include "g729FixedPointMath.h"
#include "codebooks.h"
#include "LP2LSPConversion.h"
/* buffers allocation */
static const word16_t SIDqLSPInitialValues[NB_LSP_COEFF] = {31441, 27566, 21458, 13612, 4663, -4663, -13612, -21458, -27566, -31441}; /* in Q0.15 the initials values for the previous qLSP buffer */
......@@ -231,6 +232,7 @@ void computeComfortNoiseExcitationVector(word16_t targetGain, uint16_t *randomGe
/* -(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): bitStreamLength : in bytes, length of previous buffer */
/* -(i/o): excitationVector in Q0, accessed in range [-L_PAST_EXCITATION,L_FRAME-1] */
/* [-154,79] */
/* -(o): LP: 20 LP coefficients in Q12 */
......@@ -240,30 +242,99 @@ void computeComfortNoiseExcitationVector(word16_t targetGain, uint16_t *randomGe
/* 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]) {
void decodeSIDframe(bcg729CNGChannelContextStruct *CNGChannelContext, uint8_t previousFrameIsActiveFlag, uint8_t *bitStream, uint8_t bitStreamLength, word16_t *excitationVector, word16_t *previousqLSP, word16_t *LP, uint16_t *pseudoRandomSeed, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF], uint8_t rfc3389PayloadFlag) {
int i;
word16_t interpolatedqLSP[NB_LSP_COEFF]; /* interpolated qLSP in Q0.15 */
/* if this is a SID frame, decode received parameters */
if (bitStream!=NULL) {
word16_t currentqLSF[NB_LSP_COEFF]; /* buffer to the current qLSF in Q2.13 */
uint8_t L0 = (bitStream[0]>>7)&0x01;
uint8_t L1Index = (bitStream[0]>>2)&0x1F;
uint8_t L2Index = ((bitStream[0]&0x03)<<2) | ((bitStream[1]>>6)&0x03);
/* retrieve gain from codebook according to Gain parameter */
CNGChannelContext->receivedSIDGain = SIDGainCodebook[((bitStream[1])>>1)&0x1F];
/* Use L1 and L2(parameter for first and second stage vector of LSF quantizer) to retrieve LSP using subset index to address the complete L1 and L2L3 codebook */
for (i=0; i<NB_LSP_COEFF/2; i++) {
currentqLSF[i]=ADD16(L1[L1SubsetIndex[L1Index]][i], L2L3[L2SubsetIndex[L2Index]][i]);
}
for (i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
currentqLSF[i]=ADD16(L1[L1SubsetIndex[L1Index]][i], L2L3[L3SubsetIndex[L2Index]][i]);
}
computeqLSF(currentqLSF, previousLCodeWord, L0, noiseMAPredictor, noiseMAPredictorSum);
if (rfc3389PayloadFlag) {
int j;
word32_t LPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */
word16_t LPCoefficientsQ12[NB_LSP_COEFF]; /* in Q12 */
word32_t previousIterationLPCoefficients[NB_LSP_COEFF+1]; /* in Q4.27 */
uint8_t CNFilterOrder = (bitStreamLength-1); /* first byte is noise energy level */
word16_t k[NB_LSP_COEFF];
word32_t receivedSIDGainLog;
if (CNFilterOrder>NB_LSP_COEFF) { /* if rfc3389 payload have a filter order > than supported, just ignore the last coefficients */
CNFilterOrder = NB_LSP_COEFF;
}
/* retrieve gain from codebook according to Gain parameter */
//CNGChannelContext->receivedSIDGain = SIDGainCodebook[bitStream[0]];
/* received parameter is -(10*log10(meanE) -90) so retrieve mean energy : 10^((param+90)/10) */
/* but expected parameter is a gain applied to single sample so sqrt of previous result */
receivedSIDGainLog = ADD32(-bitStream[0], 90);
if (receivedSIDGainLog > 66) {
receivedSIDGainLog = 66; /* noise level shall not be too high in any case */
} /* receivedSIDGainLog is param+90 in Q0 */
receivedSIDGainLog = MULT16_16(receivedSIDGainLog, 680); /* 680 is 1/(10*log10(2)) in Q11 -> receivedSIDGainLog is ((param+90)/10)/log10(2) = log2(meanE) in Q11 */
receivedSIDGainLog = g729Exp2_Q11Q16(receivedSIDGainLog); /* receivedSIDGainLog in meanE in Q16 */
if (receivedSIDGainLog > 0 ) { /* avoid arithmetic problem if energy is too low */
CNGChannelContext->receivedSIDGain = (word16_t)(SHR(g729Sqrt_Q0Q7(receivedSIDGainLog), 12)); /* output of sqrt in Q15, result needed in Q3 */
if (CNGChannelContext->receivedSIDGain < SIDGainCodebook[0]) {
CNGChannelContext->receivedSIDGain = SIDGainCodebook[0];
}
} else { /* minimum target gain extracted from codebook */
CNGChannelContext->receivedSIDGain = SIDGainCodebook[0];
}
/* retrieve LP from rfc3389 payload*/
/* rebuild the LP coefficients using algo given in G711 Appendix II section 5.2.1.3 */
/* first get back the quantized reflection coefficients from Index as in RFC3389 3.2 */
for (i=0; i<CNFilterOrder; i++) {
k[i] = MULT16_16(ADD16(bitStream[i+1],127), 258); /* k in Q15 */
}
for (i=CNFilterOrder; i<NB_LSP_COEFF; i++) { /* rfc3389 payload may provide a filter of order < NB_LSP_COEFF */
k[i] = 0; /* in that case, just set the last coefficients to 0 */
}
/* rebuild LP coefficients */
LPCoefficients[0] = ONE_IN_Q27;
LPCoefficients[1] = -SHL(k[0],12);
for (i=2; i<NB_LSP_COEFF+1; i++) {
/* update the previousIterationLPCoefficients needed for this one */
for (j=1; j<i; j++) {
previousIterationLPCoefficients[j] = LPCoefficients[j];
}
/* convert qLSF to qLSP: qLSP = cos(qLSF) */
for (i=0; i<NB_LSP_COEFF; i++) {
CNGChannelContext->qLSP[i] = g729Cos_Q13Q15(currentqLSF[i]); /* ouput in Q0.15 */
LPCoefficients[i] = -SHL(k[i-1],16); /* current coeff in Q31 while older one in Q27*/
for (j=1; j<i; j++) {
LPCoefficients[j] = MAC32_32_Q31(LPCoefficients[j], LPCoefficients[i], previousIterationLPCoefficients[i-j]); /*LPCoefficients in Q27 except for LPCoefficients[i] in Q31 */
}
LPCoefficients[i] = SHR(LPCoefficients[i], 4);
}
/* convert with rounding the LP Coefficients form Q27 to Q12, ignore first coefficient which is always 1 */
for (i=0; i<NB_LSP_COEFF; i++) {
LPCoefficientsQ12[i] = (word16_t)SATURATE(PSHR(LPCoefficients[i+1], 15), MAXINT16);
}
/* compute LSP from LP as we need to store LSP in context as the LP to use are interpolated with previous ones. Note: use LSP as qLSP */
if (!LP2LSPConversion(LPCoefficientsQ12, CNGChannelContext->qLSP)) {
/* unable to find the 10 roots repeat previous LSP */
memcpy(CNGChannelContext->qLSP, previousqLSP, NB_LSP_COEFF*sizeof(word16_t));
}
} else { /* regular G729 SID payload on 2 bytes */
word16_t currentqLSF[NB_LSP_COEFF]; /* buffer to the current qLSF in Q2.13 */
uint8_t L0 = (bitStream[0]>>7)&0x01;
uint8_t L1Index = (bitStream[0]>>2)&0x1F;
uint8_t L2Index = ((bitStream[0]&0x03)<<2) | ((bitStream[1]>>6)&0x03);
/* retrieve gain from codebook according to Gain parameter */
CNGChannelContext->receivedSIDGain = SIDGainCodebook[((bitStream[1])>>1)&0x1F];
/* Use L1 and L2(parameter for first and second stage vector of LSF quantizer) to retrieve LSP using subset index to address the complete L1 and L2L3 codebook */
for (i=0; i<NB_LSP_COEFF/2; i++) {
currentqLSF[i]=ADD16(L1[L1SubsetIndex[L1Index]][i], L2L3[L2SubsetIndex[L2Index]][i]);
}
for (i=NB_LSP_COEFF/2; i<NB_LSP_COEFF; i++) {
currentqLSF[i]=ADD16(L1[L1SubsetIndex[L1Index]][i], L2L3[L3SubsetIndex[L2Index]][i]);
}
computeqLSF(currentqLSF, previousLCodeWord, L0, noiseMAPredictor, noiseMAPredictorSum);
/* convert qLSF to qLSP: qLSP = cos(qLSF) */
for (i=0; i<NB_LSP_COEFF; i++) {
CNGChannelContext->qLSP[i] = g729Cos_Q13Q15(currentqLSF[i]); /* ouput in Q0.15 */
}
}
} /* Note: Itu implementation have information to sort missing and untransmitted packets and perform reconstruction of missed SID packet when it detects it, we cannot differentiate lost vs untransmitted packet so we don't do it */
......
......@@ -41,14 +41,16 @@ void computeComfortNoiseExcitationVector(word16_t targetGain, uint16_t *randomGe
/* -(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): bitStreamLength : in bytes, length of previous buffer */
/* -(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 */
/* -(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 */
/* -(i) rfc3389PayloadFlag: true when CN payload follow rfc3389 */
/* */
/*******************************************************************************************/
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]);
void decodeSIDframe(bcg729CNGChannelContextStruct *CNGChannelContext, uint8_t previousFrameIsActiveFlag, uint8_t *bitStream, uint8_t bitStreamLength, word16_t *excitationVector, word16_t *previousqLSP, word16_t *LP, uint16_t *pseudoRandomSeed, word16_t previousLCodeWord[MA_MAX_K][NB_LSP_COEFF], uint8_t rfc3389PayloadFlag);
#endif /* ifndef CNG_H */
......@@ -33,13 +33,13 @@
/* -(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) reflectionCoefficient: 10 values Q31, k generated during Levinson */
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
/* -(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) {
void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t *residualEnergy) {
/*********************************************************************************/
/* Compute the LP Coefficient using Levinson-Durbin algo spec 3.2.2 */
/*********************************************************************************/
......@@ -73,6 +73,7 @@ void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoeff
/* init */
LPCoefficients[0] = ONE_IN_Q27;
LPCoefficients[1] = -DIV32_32_Q27(autoCorrelationCoefficients[1], autoCorrelationCoefficients[0]); /* result in Q27(but<1) */
reflectionCoefficients[0] = SHL(LPCoefficients[1],4); /* k[0] is -r1/r0 in Q31 */
/* E = r0(1 - a[1]^2) in Q31 */
E = MULT32_32_Q31(autoCorrelationCoefficients[0], SUB32(ONE_IN_Q31, MULT32_32_Q23(LPCoefficients[1], LPCoefficients[1]))); /* LPCoefficient[1] is in Q27, using a Q23 operation will result in a Q31 variable */
......@@ -91,9 +92,7 @@ void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoeff
/* a[i] = -sum/E */
LPCoefficients[i] = -DIV32_32_Q31(sum,E); /* LPCoefficient of current iteration is in Q31 for now, it will be set to Q27 at the end of this iteration */
if (i==2) { /* parameter k[1] from eq8 in 3.2.2 needed by VAD */
*reflectionCoefficient = LPCoefficients[i];
}
reflectionCoefficients[i-1] = LPCoefficients[i]; /* k[1] is needed by VAD others by RFC3389 RTP payload for Comfort Noise spectral information encoding */
/* iterations j = 1..i-1 */
/* a[j] += a[i]*a[i-j] */
......@@ -120,6 +119,8 @@ void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoeff
/* parameters: */
/* -(i) signal: 240 samples in Q0, the last 40 are from next frame */
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
/* -(o) reflectionCoefficient: 10 values Q31, k generated by Levinson */
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
/* -(o) reflectionCoefficient: in Q31, k[1] generated during Levinson */
/* Durbin LP coefficient generation and needed for VAD */
/* -(o) autoCorrelationCoefficients : used internally but needed by VAD */
......@@ -130,7 +131,7 @@ void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoeff
/* -(i) autoCorrelationCoefficientsNumber number of coeff to be computed*/
/* 13 if we are using them for VAD, only 11 otherwise */
/*****************************************************************************/
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t *reflectionCoefficient, word32_t autoCorrelationCoefficients[], word32_t noLagAutocorrelationCoefficients[], int8_t *autoCorrelationCoefficientsScale, uint8_t autoCorrelationCoefficientsNumber)
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t autoCorrelationCoefficients[], word32_t noLagAutocorrelationCoefficients[], int8_t *autoCorrelationCoefficientsScale, uint8_t autoCorrelationCoefficientsNumber)
{
int i,j;
word16_t windowedSignal[L_LP_ANALYSIS_WINDOW];
......@@ -207,7 +208,7 @@ void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t *reflec
}
/* convert to LP using Levinson-Durbin algo described in sepc 3.2.2 */
autoCorrelation2LP(autoCorrelationCoefficients, LPCoefficientsQ12, reflectionCoefficient, &residualEnergy);
autoCorrelation2LP(autoCorrelationCoefficients, LPCoefficientsQ12, reflectionCoefficients, &residualEnergy);
return;
}
......@@ -27,13 +27,14 @@
/* -(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) reflectionCoefficients: 10 values Q31, k generated during Levinson*/
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
/* -(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);
void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t *residualEnergy);
/*****************************************************************************/
/* computeLP : As described in spec 3.2.1 and 3.2.2 : Windowing, */
......@@ -41,9 +42,17 @@ void autoCorrelation2LP(word32_t autoCorrelationCoefficients[], word16_t LPCoeff
/* parameters: */
/* -(i) signal: 240 samples in Q0, the last 40 are from next frame */
/* -(o) LPCoefficientsQ12: 10 LP coefficients in Q12 */
/* -(o) reflectionCoefficient: 10 values Q31, k generated by Levinson */
/* Durbin LP coefficient generation and needed for VAD and RFC3389 */
/* -(o) reflectionCoefficient: in Q31, k[1] generated during Levinson */
/* Durbin LP coefficient generation and needed for VAD */
/* */
/* -(o) autoCorrelationCoefficients : used internally but needed by VAD */
/* scale is variable */
/* -(o) noLagautoCorrelationCoefficients : needed by DTX */
/* scale is variable */
/* -(o) autoCorrelationCoefficientsScale : scale factor of previous buf */
/* -(i) autoCorrelationCoefficientsNumber number of coeff to be computed*/
/* 13 if we are using them for VAD, only 11 otherwise */
/*****************************************************************************/
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t *reflectionCoefficient, word32_t autoCorrelationCoefficients[], word32_t noLagAutocorrelationCoefficients[], int8_t *autoCorrelationCoefficientsScale, uint8_t autoCorrelationCoefficientsNumber);
void computeLP(word16_t signal[], word16_t LPCoefficientsQ12[], word32_t reflectionCoefficients[], word32_t autoCorrelationCoefficients[], word32_t noLagAutocorrelationCoefficients[], int8_t *autoCorrelationCoefficientsScale, uint8_t autoCorrelationCoefficientsNumber);
#endif /* ifndef COMPUTELP_H */
......@@ -100,12 +100,14 @@ void closeBcg729DecoderChannel(bcg729DecoderChannelContextStruct *decoderChannel
/* parameters: */
/* -(i) decoderChannelContext : the channel context data */
/* -(i) bitStream : 15 parameters on 80 bits */
/* -(i): bitStreamLength : in bytes, length of previous buffer */
/* -(i) frameErased: flag: true, frame has been erased */
/* -(i) SIDFrameFlag: flag: true, frame is a SID one */
/* -(i) rfc3389PayloadFlag: true when CN payload follow rfc3389 */
/* -(o) signal : a decoded frame 80 samples (16 bits PCM) */
/* */
/*****************************************************************************/
void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t frameErasureFlag, uint8_t SIDFrameFlag, int16_t signal[])
void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uint8_t bitStream[], uint8_t bitStreamLength, uint8_t frameErasureFlag, uint8_t SIDFrameFlag, uint8_t rfc3389PayloadFlag, int16_t signal[])
{
int i;
uint16_t parameters[NB_PARAMETERS];
......@@ -165,7 +167,7 @@ void bcg729Decoder(bcg729DecoderChannelContextStruct *decoderChannelContext, uin
/* this is a SID frame, process it using the dedicated function */
if (SIDFrameFlag == 1) {
decodeSIDframe(decoderChannelContext->CNGChannelContext, decoderChannelContext->previousFrameIsActiveFlag, bitStream, &(decoderChannelContext->excitationVector[L_PAST_EXCITATION]), decoderChannelContext->previousqLSP, LP, &(decoderChannelContext->CNGpseudoRandomSeed), decoderChannelContext->previousLCodeWord);
decodeSIDframe(decoderChannelContext->CNGChannelContext, decoderChannelContext->previousFrameIsActiveFlag, bitStream, bitStreamLength, &(decoderChannelContext->excitationVector[L_PAST_EXCITATION]), decoderChannelContext->previousqLSP, LP, &(decoderChannelContext->CNGpseudoRandomSeed), decoderChannelContext->previousLCodeWord, rfc3389PayloadFlag);
decoderChannelContext->previousFrameIsActiveFlag = 0;
/* loop over the two subframes */
......
......@@ -108,9 +108,7 @@ static void sumAutocorrelationCoefficients(word32_t autoCorrelationCoefficients[
/*****************************************************************************/
static uint8_t residualEnergyQuantization(word32_t residualEnergy, int8_t residualEnergyScale, int8_t *decodedLogEnergy) {
word32_t acc;
//acc = SUB32(g729Log2_Q0Q16(residualEnergy), ADD32(676458, (int32_t)(residualEnergyScale<<16))); /* -676458 is log2(aw/(NCur*80)) acc is log2(E') in Q16 aw=0.125*/
//acc = SUB32(g729Log2_Q0Q16(residualEnergy), ADD32(610922, (int32_t)(residualEnergyScale<<16))); /* -676458 is log2(aw/(NCur*80)) acc is log2(E') in Q16 aw=0.25*/
acc = SUB32(g729Log2_Q0Q16(residualEnergy), ADD32(479849, (int32_t)(residualEnergyScale<<16))); /* -479849 is log2(aw/(NCur*80)) acc is log2(E') in Q16 aw = 1 */
acc = SUB32(g729Log2_Q0Q16(residualEnergy), ADD32(479849, (int32_t)(residualEnergyScale<<16))); /* -479849 is log2(aw/(NCur*80)) acc is log2(E') in Q16 aw = 1 as we use unlagged autocorrelation coefficients */
acc = SHR32(acc,1); /* acc = log2(E') in Q15 */
acc = MULT16_32_Q15(INV_LOG2_10_Q15, acc); /* acc log10(E') in Q15 */
......@@ -142,7 +140,7 @@ static uint8_t residualEnergyQuantization(word32_t residualEnergy, int8_t residu
return 6+steps;
} else { /* quantized energy support up to 66dB */
*decodedLogEnergy = 66;
return 32;
return 31;
}
}
......@@ -271,7 +269,7 @@ void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *
word32_t summedAutocorrelationCoefficients[NB_LSP_COEFF+1];
word16_t LPCoefficients[NB_LSP_COEFF]; /* in Q12 */
word16_t LSPCoefficients[NB_LSP_COEFF]; /* in Q15 */
word32_t reflectionCoefficient; /* not used here, by product of LP coefficients computation */
word32_t reflectionCoefficients[NB_LSP_COEFF]; /* product of LP Computation, may be used if we need to generate the RFC3389 payload */
word32_t residualEnergy; /* in variable scale(summedAutocorrelationCoefficientsScale) computed together with LP coefficients */
int8_t summedAutocorrelationCoefficientsScale;
uint8_t frameType;
......@@ -295,7 +293,7 @@ void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *
summedAutocorrelationCoefficients, &summedAutocorrelationCoefficientsScale);
/* compute LP filter coefficients */
autoCorrelation2LP(summedAutocorrelationCoefficients, LPCoefficients, &reflectionCoefficient, &residualEnergy); /* output residualEnergy with the same scale of input summedAutocorrelationCoefficients */
autoCorrelation2LP(summedAutocorrelationCoefficients, LPCoefficients, reflectionCoefficients, &residualEnergy); /* output residualEnergy with the same scale of input summedAutocorrelationCoefficients */
/* determine type of frame SID or untrasmitted */
if (DTXChannelContext->previousVADflag == 1) { /* if previous frame was active : we must generate a SID frame spec B.10 */
......@@ -348,7 +346,7 @@ void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *
word32_t SIDLPCAutocorrelationCoefficients[NB_LSP_COEFF+1];
int8_t SIDLPCAutocorrelationCoefficientsScale;
word16_t pastAverageLPCoefficients[NB_LSP_COEFF]; /* in Q12 */
word32_t pastAverageReflectionCoefficient; /* not used here, by product of LP coefficients computation */
word32_t pastAverageReflectionCoefficients[NB_LSP_COEFF]; /* produced by LP computation, may be used if we have to generate RFC3389 payload */
word32_t pastAverageResidualEnergy; /* not used here, by-product of LP coefficients computation */
/* reset frame count */
......@@ -359,11 +357,13 @@ void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *
SIDLPCAutocorrelationCoefficients, &SIDLPCAutocorrelationCoefficientsScale);
/* compute past average LP filter coefficients Ap in B4.2.2 */
autoCorrelation2LP(SIDLPCAutocorrelationCoefficients, pastAverageLPCoefficients, &pastAverageReflectionCoefficient, &pastAverageResidualEnergy); /* output residualEnergy with the same scale of input summedAutocorrelationCoefficients */
autoCorrelation2LP(SIDLPCAutocorrelationCoefficients, pastAverageLPCoefficients, pastAverageReflectionCoefficients, &pastAverageResidualEnergy); /* output residualEnergy with the same scale of input summedAutocorrelationCoefficients */
/* select coefficients according to eq B.17 we have Ap in SIDLPCoefficients and At in LPCoefficients, store result, in Q12 in SIDLPCoefficients */
/* check distance beetwen currently used filter and past filter : compute LPCoefficentAutocorrelation for the past average filter */
computeLPCoefficientAutocorrelation(pastAverageLPCoefficients, DTXChannelContext->SIDLPCoefficientAutocorrelation);
DTXChannelContext->decodedLogEnergy = decodedLogEnergy; /* store frame mean energy for RFC3389 payload generation */
if (compareLPCFilters(DTXChannelContext->SIDLPCoefficientAutocorrelation, summedAutocorrelationCoefficients, residualEnergy, THRESHOLD3_IN_Q20) == 0) { /* use the past average filter */
/* generate LSP coefficient using the past LP coefficients */
......@@ -372,6 +372,8 @@ void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *
memcpy(LSPCoefficients, previousqLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
}
/* LPCoefficientAutocorrelation are already in DTXChannelContext */
/* save the reflection coefficients in the DTX context as they will be requested to generate RFC3389 payload */
memcpy(DTXChannelContext->reflectionCoefficients, pastAverageReflectionCoefficients, NB_LSP_COEFF*sizeof(word32_t));
} else { /* use filter computed on current and previous frame */
/* compute the LPCoefficientAutocorrelation for this filter and store them in DTXChannel */
computeLPCoefficientAutocorrelation(LPCoefficients, DTXChannelContext->SIDLPCoefficientAutocorrelation);
......@@ -380,6 +382,8 @@ void encodeSIDFrame(bcg729DTXChannelContextStruct *DTXChannelContext, word16_t *
/* unable to find the 10 roots repeat previous LSP */
memcpy(LSPCoefficients, previousqLSPCoefficients, NB_LSP_COEFF*sizeof(word16_t));
}
/* save the reflection coefficients in the DTX context as they will be requested to generate RFC3389 payload */
memcpy(DTXChannelContext->reflectionCoefficients, reflectionCoefficients, NB_LSP_COEFF*sizeof(word32_t));
}
/* update previousLSP coefficient buffer */
......
......@@ -137,7 +137,7 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
word16_t impulseResponseInput[L_SUBFRAME]; /* input buffer for the impulse response computation: in Q12, 1 followed by all zeros see spec A3.5*/
/* used for VAD */
word32_t reflectionCoefficient = 0; /* in Q31, computed during LP generation */
word32_t reflectionCoefficients[NB_LSP_COEFF]; /* in Q31, computed during LP generation, reflectionCoefficients[1] is requested by VAD, the others are stored in context if we cover RFC3389 payload generation */
word32_t autoCorrelationCoefficients[NB_LSP_COEFF+3]; /* if VAD is enabled we must compute 13 coefficients, 11 otherwise but used only internally by computeLP function in that case */
word32_t noLagAutoCorrelationCoefficients[NB_LSP_COEFF+3]; /* DTX must have access to autocorrelation Coefficients on which lag windowing as not been applied */
int8_t autoCorrelationCoefficientsScale; /* autocorrelation coefficients are normalised by computeLP, must get their scaling factor */
......@@ -148,7 +148,7 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
/* use the whole signal Buffer for windowing and autocorrelation */
/* autoCorrelation Coefficients are computed and used internally, in case of VAD we must compute and retrieve 13 coefficients, compute only 11 when VAD is disabled */
computeLP(encoderChannelContext->signalBuffer, LPCoefficients, &reflectionCoefficient, autoCorrelationCoefficients, noLagAutoCorrelationCoefficients, &autoCorrelationCoefficientsScale, (encoderChannelContext->VADChannelContext != NULL)?NB_LSP_COEFF+3:NB_LSP_COEFF+1);
computeLP(encoderChannelContext->signalBuffer, LPCoefficients, reflectionCoefficients, autoCorrelationCoefficients, noLagAutoCorrelationCoefficients, &autoCorrelationCoefficientsScale, (encoderChannelContext->VADChannelContext != NULL)?NB_LSP_COEFF+3:NB_LSP_COEFF+1);
/*** compute LSP: it might fail, get the previous one in this case ***/
if (!LP2LSPConversion(LPCoefficients, LSPCoefficients)) {
/* unable to find the 10 roots repeat previous LSP */
......@@ -167,9 +167,9 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
LSFCoefficients[i] = g729Acos_Q15Q13(LSPCoefficients[i]);
}
VADflag = bcg729_vad(encoderChannelContext->VADChannelContext, reflectionCoefficient, LSFCoefficients, autoCorrelationCoefficients, autoCorrelationCoefficientsScale, encoderChannelContext->signalCurrentFrame);
VADflag = bcg729_vad(encoderChannelContext->VADChannelContext, reflectionCoefficients[1], LSFCoefficients, autoCorrelationCoefficients, autoCorrelationCoefficientsScale, encoderChannelContext->signalCurrentFrame);
/* call encodeSIDFrame even if it is a voice frame as it will update DTXContext with current VADflag */
/* call encodeSIDFrame even if it is a voice frame as it will update DTXContext with current VADflag : TODO : move updateDTXContext in the encodeSIDFrame as part of the update is performed in it anyway */
encodeSIDFrame(encoderChannelContext->DTXChannelContext, encoderChannelContext->previousLSPCoefficients, encoderChannelContext->previousqLSPCoefficients, VADflag, encoderChannelContext->previousqLSF, &(encoderChannelContext->excitationVector[L_PAST_EXCITATION]), qLPCoefficients, bitStream, bitStreamLength);
if (VADflag == 0 ) { /* NOISE frame has been encoded */
......@@ -383,3 +383,25 @@ void bcg729Encoder(bcg729EncoderChannelContextStruct *encoderChannelContext, int
return;
}
/*****************************************************************************/
/* bcg729GetRFC3389Payload : return the comfort noise payload according to */
/* RFC3389 for the last CN frame generated by encoder */
/* */
/* parameters: */
/* -(i) encoderChannelContext : retrieve the last CN frame encoded */
/* using this context */
/* -(o) payload : 11 parameters following RFC3389 with filter order 10 */
/* */
/*****************************************************************************/
void bcg729GetRFC3389Payload(bcg729EncoderChannelContextStruct *encoderChannelContext, uint8_t payload[]) {
int i;
/* decodedLogEnergy is the frame mean energy, range [-12,66[, RFC3389 ask for DBov value, max mean energy would be 10log10(2^15*2^15) -> 90 so -90 to switch to DBov */
payload[0] = -(encoderChannelContext->DTXChannelContext->decodedLogEnergy - 90);
/* use last reflection coefficients stored in DTX context and convert them as specified in RFC3389 : Ni = (ki in Q15)/258 + 127 */
for (i=0; i<NB_LSP_COEFF; i++) {
payload[i+1] = (uint8_t)ADD16((word16_t)SHR(MULT16_32_Q15(127/* 1/258 in Q15 */, -encoderChannelContext->DTXChannelContext->reflectionCoefficients[i]), 16), 127); /* ki in Q31 * (1/258 in Q15) -> result in Q31, shift right by 16 -> Q15 */
}
}
......@@ -22,6 +22,11 @@
#define TYPEDEF_H
#include <stdint.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "codecParameters.h"
#include "bcg729/encoder.h"
#include "bcg729/decoder.h"
......@@ -72,6 +77,8 @@ struct bcg729DTXChannelContextStruct_struct {
word16_t smoothedSIDGain; /* gain in Q3 */
uint16_t pseudoRandomSeed; /* seed used in the pseudo random number generator for excitation generation */
word16_t qLSPCoefficients[NB_LSP_COEFF]; /* current Quantized LSP coefficient in Q15, saved to be re-used in case of untransmitted frame */
word32_t reflectionCoefficients[NB_LSP_COEFF]; /* used to generate the RFC3389 payload, generated during LP computation */
int8_t decodedLogEnergy; /* log10(frame residual energy), used to generate noise level for RFC3389 paylaod */
};
typedef struct bcg729DTXChannelContextStruct_struct bcg729DTXChannelContextStruct;
......
check_PROGRAMS=adaptativeCodebookSearchTest computeAdaptativeCodebookGainTest computeLPTest computeWeightedSpeechTest decodeAdaptativeCodeVectorTest decodeFixedCodeVectorTest decodeGainsTest decodeLSPTest \
decoderTest encoderTest decoderMultiChannelTest encoderMultiChannelTest findOpenLoopPitchDelayTest fixedCodebookSearchTest g729FixedPointMathTest gainQuantizationTest interpolateqLSPAndConvert2LPTest \
LP2LSPConversionTest LPSynthesisFilterTest LSPQuantizationTest postFilterTest postProcessingTest preProcessingTest computeNoiseExcitationTest CNGdecoderTest encoderVADTest
LP2LSPConversionTest LPSynthesisFilterTest LSPQuantizationTest postFilterTest postProcessingTest preProcessingTest computeNoiseExcitationTest CNGdecoderTest CNGRFC3389decoderTest encoderVADTest
util_src=$(top_srcdir)/test/src/testUtils.c
adaptativeCodebookSearchTest_SOURCES=$(top_srcdir)/test/src/adaptativeCodebookSearchTest.c $(util_src)
......@@ -12,6 +12,7 @@ decodeFixedCodeVectorTest_SOURCES=$(top_srcdir)/test/src/decodeFixedCodeVectorTe
decodeGainsTest_SOURCES=$(top_srcdir)/test/src/decodeGainsTest.c $(util_src)
decodeLSPTest_SOURCES=$(top_srcdir)/test/src/decodeLSPTest.c $(util_src)
decoderTest_SOURCES=$(top_srcdir)/test/src/decoderTest.c $(util_src)
CNGRFC3389decoderTest_SOURCES=$(top_srcdir)/test/src/CNGRFC3389decoderTest.c $(util_src)
CNGdecoderTest_SOURCES=$(top_srcdir)/test/src/CNGdecoderTest.c $(util_src)
decoderMultiChannelTest_SOURCES=$(top_srcdir)/test/src/decoderMultiChannelTest.c $(util_src)
encoderTest_SOURCES=$(top_srcdir)/test/src/encoderTest.c $(util_src)
......
/*
decoderTest.c
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.
*/
/*****************************************************************************/
/* */
/* Test Program for decoder */
/* Input: 15 parameters and the frame erasure flag on each row of a */
/* a text CSV file. */
/* Ouput: the reconstructed signal : each frame (80 16 bits PCM values) */
/* on a row of a text CSV file */
/* */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "typedef.h"
#include "codecParameters.h"
#include "utils.h"
#include "testUtils.h"
#include "bcg729/decoder.h"
int main(int argc, char *argv[] )
{
/*** get calling argument ***/
char *filePrefix;
getArgument(argc, argv, &filePrefix); /* check argument and set filePrefix if needed */
/*** input and output file pointers ***/
FILE *fpInput;
FILE *fpOutput;
FILE *fpBinOutput;
/*** input and output buffers ***/
uint16_t inputBuffer[NB_PARAMETERS+2]; /* input buffer: an array containing the 15 parameters and the frame erasure flag and VAD flag */
uint8_t bitStream[11]; /* binary input for the decoder */
int16_t outputBuffer[L_FRAME]; /* output buffer: the reconstructed signal */
/*** inits ***/
/* open the input file */
if ( (fpInput = fopen(argv[1], "r")) == NULL) {
printf("%s - Error: can't open file %s\n", argv[0], argv[1]);
exit(-1);
}
/* create the output file(filename is the same than input file with the .out extension) */
char *outputFile = malloc((strlen(filePrefix)+5)*sizeof(char));
sprintf(outputFile, "%s.out",filePrefix);
if ( (fpOutput = fopen(outputFile, "w")) == NULL) {
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
exit(-1);
}
sprintf(outputFile, "%s.pcm",filePrefix);
if ( (fpBinOutput = fopen(outputFile, "wb")) == NULL) {
printf("%s - Error: can't create file %s\n", argv[0], outputFile);
exit(-1);
}
/*** init of the tested bloc ***/
bcg729DecoderChannelContextStruct *decoderChannelContext = initBcg729DecoderChannel();
/*** initialisation complete ***/
/* perf measurement */
clock_t start, end;
double cpu_time_used=0.0;
int framesNbr =0;
/* increase LOOP_N to increase input length and perform a more accurate profiling or perf measurement */
#define LOOP_N 1
int j;
for (j=0; j<LOOP_N; j++) {
/* perf measurement */
/*** loop over input file ***/
while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]), &(inputBuffer[10]), &(inputBuffer[11]), &(inputBuffer[12]), &(inputBuffer[13]), &(inputBuffer[14]), &(inputBuffer[15]), &(inputBuffer[16]))==17) /* index 4 and 5 are inverted to get P0 in 4 and P1 in 5 in the array */
{ /* input buffer contains the parameters and in [15] the frame erasure flag */
int i;
uint8_t bitStreamLength;
framesNbr++;
if (inputBuffer[16]==1) { /* active frame */
parametersArray2BitStream(inputBuffer, bitStream);
bitStreamLength = 10;
} else { /* SID frame */
if (inputBuffer[16]==0) {/* non transmitted frame */
inputBuffer[15] = 1;
bitStreamLength = 0;
} else { /* actual SID frame */
for (i=0; i<11; i++) {
bitStream[i] = inputBuffer[i];
}
bitStreamLength = 11;
}
}
start = clock();
bcg729Decoder(decoderChannelContext, inputBuffer[15]==0?bitStream:NULL, bitStreamLength, inputBuffer[15], inputBuffer[16]!=1?1:0, 1, outputBuffer);
end = clock();
cpu_time_used += ((double) (end - start));
/* write the output to the output files (only on first loop of perf measurement)*/
if (j==0) {
fprintf(fpOutput,"%d",outputBuffer[0]);
for (i=1; i<L_FRAME; i++) {
fprintf(fpOutput,",%d",outputBuffer[i]);
}
fprintf(fpOutput,"\n");
/* write the ouput to raw data file */
fwrite(outputBuffer, sizeof(int16_t), L_FRAME, fpBinOutput);
}
}
/* perf measurement */
rewind(fpInput);
}
closeBcg729DecoderChannel(decoderChannelContext);
/* Perf measurement: uncomment next line to print cpu usage */
printf("Decode %d frames in %f seconds : %f us/frame\n", framesNbr, cpu_time_used/CLOCKS_PER_SEC, cpu_time_used*1000000/((double)framesNbr*CLOCKS_PER_SEC));
/* perf measurement */
exit (0);
}
......@@ -98,21 +98,25 @@ int main(int argc, char *argv[] )
while(fscanf(fpInput, "%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd,%hd", &(inputBuffer[0]), &(inputBuffer[1]), &(inputBuffer[2]), &(inputBuffer[3]), &(inputBuffer[4]), &(inputBuffer[5]), &(inputBuffer[6]), &(inputBuffer[7]), &(inputBuffer[8]), &(inputBuffer[9]), &(inputBuffer[10]), &(inputBuffer[11]), &(inputBuffer[12]), &(inputBuffer[13]), &(inputBuffer[14]), &(inputBuffer[15]), &(inputBuffer[16]))==17) /* index 4 and 5 are inverted to get P0 in 4 and P1 in 5 in the array */
{ /* input buffer contains the parameters and in [15] the frame erasure flag */
int i;
uint8_t bitStreamLength;
framesNbr++;
if (inputBuffer[16]==1) { /* active frame */
parametersArray2BitStream(inputBuffer, bitStream);
bitStreamLength = 10;
} else { /* SID frame */
if (inputBuffer[16]==0) {/* non transmitted frame */
inputBuffer[15] = 1;
bitStreamLength = 0;
} else { /* actual SID frame */
CNGparametersArray2BitStream(inputBuffer, bitStream);
bitStreamLength = 2;
}
}
start = clock();
bcg729Decoder(decoderChannelContext, inputBuffer[15]==0?bitStream:NULL, inputBuffer[15], inputBuffer[16]!=1?1:0, outputBuffer);
bcg729Decoder(decoderChannelContext, inputBuffer[15]==0?bitStream:NULL, bitStreamLength, inputBuffer[15], inputBuffer[16]!=1?1:0, 0, outputBuffer);
end = clock();
cpu_time_used += ((double) (end - start));
......
/*
VADTest.c
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.
*/
/*****************************************************************************/
/* */
/* Test Program for computeLP Bloc */