|
|
//
// ITU-T G.723 Floating Point Speech Coder ANSI C Source Code. Version 1.00
// copyright (c) 1995, AudioCodes, DSP Group, France Telecom,
// Universite de Sherbrooke, Intel Corporation. All rights reserved.
//
#include "timer.h"
#include "ctiming.h"
#include "opt.h"
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "typedef.h"
#include "cst_lbc.h"
#include "tab_lbc.h"
#include "decod.h"
#include "util_lbc.h"
#include "lpc.h"
#include "lsp.h"
#include "exc_lbc.h"
#ifdef LOG_DECODE_TIMINGS_ON // { LOG_DECODE_TIMINGS_ON
#pragma message ("Current log decode timing computations handle 2057 frames max")
void OutputDecodeTimingStatistics(char * szFileName, DEC_TIMING_INFO * pDecTimingInfo, unsigned long dwFrameCount); void OutputDecTimingDetail(FILE * pFile, DEC_TIMING_INFO * pDecTimingInfo); #endif // } LOG_DECODE_TIMINGS_ON
// This file includes the decoder main functions
//--------------------------------------------------
void Init_Decod(DECDEF *DecStat) { int i;
// Init prev Lsp to Dc
for (i = 0; i < LpcOrder; i++) DecStat->dPrevLsp[i] = LspDcTable[i];
DecStat->dp = 9; DecStat->dq = 9; }
//--------------------------------------------------
Flag Decod(float *DataBuff, Word32 *Vinp, Word16 Crc, DECDEF *DecStat) { int i,j,g;
float QntLpc[SubFrames*LpcOrder]; float AcbkCont[SubFrLen];
float LspVect[LpcOrder]; float Temp[PitchMax+Frame]; float *Dpnt;
LINEDEF Line;
#if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON) // { #if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON)
unsigned long dwStartLow; unsigned long dwStartHigh; unsigned long dwElapsed; unsigned long dwBefore; unsigned long dwDecode = 0; int bTimingThisFrame = 0; #endif // } #if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON)
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
unsigned long dwLine_Unpk = 0; unsigned long dwLsp_Inq = 0; unsigned long dwLsp_Int = 0; unsigned long dwVariousD = 0; unsigned long dwFcbk_UnpkD = 0; unsigned long dwDecod_AcbkD = 0; unsigned long dwComp_Info = 0; unsigned long dwRegen = 0; unsigned long dwSynt = 0; unsigned long dwFcbk_UnpkDTemp = 0; unsigned long dwDecod_AcbkDTemp = 0; unsigned long dwSyntTemp = 0; #endif // } DETAILED_DECODE_TIMINGS_ON
#ifdef LOG_DECODE_TIMINGS_ON // { LOG_DECODE_TIMINGS_ON
DEC_TIMING_INFO * pDecTimingInfo = NULL; #endif // } LOG_DECODE_TIMINGS_ON
#if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON) // { #if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON)
TIMER_START(bTimingThisFrame,dwStartLow,dwStartHigh); #endif // } #if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON)
#ifdef LOG_DECODE_TIMINGS_ON // { LOG_DECODE_TIMINGS_ON
if (DecStat->dwStatFrameCount < DEC_TIMING_INFO_FRAME_COUNT) { DecStat->dwStartLow = dwStartLow; DecStat->dwStartHigh = dwStartHigh; } DecStat->bTimingThisFrame = bTimingThisFrame; #endif // } LOG_DECODE_TIMINGS_ON
// Unpack the Line info
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
Line_Unpk(&Line, Vinp, &DecStat->WrkRate, Crc);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwLine_Unpk); #endif // } DETAILED_DECODE_TIMINGS_ON
if(DecStat->WrkRate == Silent) { //HACK: For handling SID frames.
//Until comfort noise generator is in place, we play
// out random noise frames.
//In Line_unpck, reset WrkRate to original setting
// and decode. We therefore should never reach this point.
memset(DataBuff, 0, sizeof(float) * Frame); //exit having filled frame with zeros leave state alone
//this will be fixed up in a later ITU release
return (Flag) False; } else if(DecStat->WrkRate == Lost) { Line.Crc = !0; } /*
Line.Crc equals one means that the line was corrupted. It shouldn't be reassigned. Otherwise, member of Line will be used uninitialized. Comment out the following two lines. muhan, 5/26/98
else { Line.Crc = Crc; } */ if (Line.Crc != 0) DecStat->Ecount++; else DecStat->Ecount = 0;
if (DecStat->Ecount > ErrMaxNum) DecStat->Ecount = ErrMaxNum;
// Inverse quantization of the LSP
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
Lsp_Inq(LspVect, DecStat->dPrevLsp, Line.LspId, Line.Crc);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwLsp_Inq); #endif // } DETAILED_DECODE_TIMINGS_ON
// Interpolate the Lsp vectors
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
Lsp_Int(QntLpc, LspVect, DecStat->dPrevLsp);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwLsp_Int); #endif // } DETAILED_DECODE_TIMINGS_ON
/* Copy the LSP vector for the next frame */ #ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
for ( i = 0 ; i < LpcOrder ; i ++ ) DecStat->dPrevLsp[i] = LspVect[i] ;
/*
* In case of no erasure, update the interpolation gain memory. * Otherwise compute the interpolation gain (Text: Section 3.10) */
if (DecStat->Ecount == 0) { g = (Line.Sfs[SubFrames-2].Mamp + Line.Sfs[SubFrames-1].Mamp) >> 1; DecStat->InterGain = FcbkGainTable[g]; } else DecStat->InterGain = DecStat->InterGain*0.75f;
// Regenerate the excitation
for (i = 0; i < PitchMax; i++) Temp[i] = DecStat->dPrevExc[i];
Dpnt = &Temp[PitchMax];
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwVariousD); #endif // } DETAILED_DECODE_TIMINGS_ON
if (DecStat->Ecount == 0) { for (i = 0; i < SubFrames; i++) { // Unpack fixed code book
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
Fcbk_Unpk(Dpnt, Line.Sfs[i], Line.Olp[i>>1], i, DecStat->WrkRate);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwFcbk_UnpkDTemp); #endif // } DETAILED_DECODE_TIMINGS_ON
// Reconstruct the excitation
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
Decod_Acbk(AcbkCont, &Temp[SubFrLen*i], Line.Olp[i>>1], Line.Sfs[i].AcLg, Line.Sfs[i].AcGn, DecStat->WrkRate);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwDecod_AcbkDTemp); #endif // } DETAILED_DECODE_TIMINGS_ON
for (j = 0; j < SubFrLen; j++) Dpnt[j] = Dpnt[j]*2.0f + AcbkCont[j];
Dpnt += SubFrLen;
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
// Cumulate stats
dwFcbk_UnpkD += dwFcbk_UnpkDTemp; dwFcbk_UnpkDTemp = 0; dwDecod_AcbkD+= dwDecod_AcbkDTemp; dwDecod_AcbkDTemp = 0; #endif // } DETAILED_DECODE_TIMINGS_ON
}
// Save the Excitation
for (j = 0; j < Frame; j++) DataBuff[j] = Temp[PitchMax+j];
// Compute interpolation index, for future use in frame erasures
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
DecStat->InterIndx = Comp_Info(Temp, Line.Olp[SubFrames/2-1]);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwComp_Info); #endif // } DETAILED_DECODE_TIMINGS_ON
// Reload back
for (j = 0; j < PitchMax; j++) Temp[j] = DecStat->dPrevExc[j]; for (j = 0; j < Frame; j++) Temp[PitchMax+j] = DataBuff[j];
#if 1 //do clipping
/* Clip newly generated samples in Temp array */ for(j = 0; j < Frame; j++) { //clip to +/- 32767.0 doing abs & compare with integer unit
//if clipping is needed shift sign bit to use as lookup table index
#define FLTCLIP(x) \
{\ const float T[2] = {32767.0f, -32767.0f};\ if ((asint(x) & 0x7fffffff) > asint(T[0]))\ x = T[((unsigned)asint(x)) >> 31];\ }
FLTCLIP(Temp[PitchMax+j]); } #endif //optclip
} else { #ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
Regen(DataBuff, Temp, DecStat->InterIndx, DecStat->InterGain, DecStat->Ecount, &DecStat->Rseed);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwRegen); #endif // } DETAILED_DECODE_TIMINGS_ON
}
// Update PrevExc for next frame
for (j = 0; j < PitchMax; j++) DecStat->dPrevExc[j] = Temp[Frame+j];
// Synthesis
Dpnt = DataBuff; for (i = 0; i < SubFrames; i++) { // Synthesize output speech
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_BEFORE(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore); #endif // } DETAILED_DECODE_TIMINGS_ON
Synt(Dpnt, &QntLpc[i*LpcOrder], DecStat);
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
TIMER_AFTER_P5(bTimingThisFrame,dwStartLow,dwStartHigh,dwBefore,dwElapsed,dwSyntTemp); #endif // } DETAILED_DECODE_TIMINGS_ON
Dpnt += SubFrLen;
#ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
// Cumulate stats
dwSynt += dwSyntTemp; dwSyntTemp = 0; #endif // } DETAILED_DECODE_TIMINGS_ON
}
#if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON) // { #if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON)
TIMER_STOP(bTimingThisFrame,dwStartLow,dwStartHigh,dwDecode); #endif // } DECODE_TIMINGS_ON
#ifdef LOG_DECODE_TIMINGS_ON // { LOG_DECODE_TIMINGS_ON
if (bTimingThisFrame && (DecStat->dwStatFrameCount < DEC_TIMING_INFO_FRAME_COUNT)) { pDecTimingInfo = &DecStat->DecTimingInfo[DecStat->dwStatFrameCount]; pDecTimingInfo->dwDecode = dwDecode; #ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
pDecTimingInfo->dwLine_Unpk = dwLine_Unpk; pDecTimingInfo->dwLsp_Inq = dwLsp_Inq; pDecTimingInfo->dwLsp_Int = dwLsp_Int; pDecTimingInfo->dwVariousD = dwVariousD; pDecTimingInfo->dwFcbk_UnpkD = dwFcbk_UnpkD; pDecTimingInfo->dwDecod_AcbkD = dwDecod_AcbkD; pDecTimingInfo->dwComp_Info = dwComp_Info; pDecTimingInfo->dwRegen = dwRegen; pDecTimingInfo->dwSynt = dwSynt; #endif // } DETAILED_DECODE_TIMINGS_ON
DecStat->dwStatFrameCount++; } else { _asm int 3; } #endif // } #if defined(DECODE_TIMINGS_ON) || defined(DETAILED_DECODE_TIMINGS_ON)
return (Flag) True; }
#ifdef LOG_DECODE_TIMINGS_ON // { LOG_DECODE_TIMINGS_ON
void OutputDecodeTimingStatistics(char * szFileName, DEC_TIMING_INFO * pDecTimingInfo, unsigned long dwFrameCount) { FILE * pFile; DEC_TIMING_INFO * pTempDecTimingInfo; DEC_TIMING_INFO dtiTemp; int i; int iCount;
pFile = fopen(szFileName, "a"); if (pFile == NULL) goto done;
#if 0
// Too verbose !!!
/* Output the detail information
*/ fprintf(pFile,"\nDetail Timing Information\n"); for ( i = 0, pTempDecTimingInfo = pDecTimingInfo ; i < dwFrameCount ; i++, pTempDecTimingInfo++ ) { fprintf(pFile, "Frame %d Detail Timing Information\n", i); OutputDecTimingDetail(pFile, pTempDecTimingInfo); } #endif
/* Compute the total information
*/ memset(&dtiTemp, 0, sizeof(DEC_TIMING_INFO)); iCount = 0;
for ( i = 0, pTempDecTimingInfo = pDecTimingInfo ; i < dwFrameCount ; i++, pTempDecTimingInfo++ ) { iCount++; dtiTemp.dwDecode += pTempDecTimingInfo->dwDecode; #ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
dtiTemp.dwLine_Unpk += pTempDecTimingInfo->dwLine_Unpk; dtiTemp.dwLsp_Inq += pTempDecTimingInfo->dwLsp_Inq; dtiTemp.dwLsp_Int += pTempDecTimingInfo->dwLsp_Int; dtiTemp.dwVariousD += pTempDecTimingInfo->dwVariousD; dtiTemp.dwFcbk_UnpkD += pTempDecTimingInfo->dwFcbk_UnpkD; dtiTemp.dwDecod_AcbkD += pTempDecTimingInfo->dwDecod_AcbkD; dtiTemp.dwComp_Info += pTempDecTimingInfo->dwComp_Info; dtiTemp.dwRegen += pTempDecTimingInfo->dwRegen; dtiTemp.dwSynt += pTempDecTimingInfo->dwSynt; #endif // } DETAILED_DECODE_TIMINGS_ON
}
if (iCount > 0) { /* Output the total information
*/ fprintf(pFile,"Total for %d frames\n", iCount); OutputDecTimingDetail(pFile, &dtiTemp);
/* Compute the average
*/ dtiTemp.dwDecode = (dtiTemp.dwDecode + (iCount / 2)) / iCount; #ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
dtiTemp.dwLine_Unpk = (dtiTemp.dwLine_Unpk + (iCount / 2)) / iCount; dtiTemp.dwLsp_Inq = (dtiTemp.dwLsp_Inq + (iCount / 2)) / iCount; dtiTemp.dwLsp_Int = (dtiTemp.dwLsp_Int + (iCount / 2)) / iCount; dtiTemp.dwVariousD = (dtiTemp.dwVariousD + (iCount / 2)) / iCount; dtiTemp.dwFcbk_UnpkD = (dtiTemp.dwFcbk_UnpkD + (iCount / 2)) / iCount; dtiTemp.dwDecod_AcbkD = (dtiTemp.dwDecod_AcbkD + (iCount / 2)) / iCount; dtiTemp.dwComp_Info = (dtiTemp.dwComp_Info + (iCount / 2)) / iCount; dtiTemp.dwRegen = (dtiTemp.dwRegen + (iCount / 2)) / iCount; dtiTemp.dwSynt = (dtiTemp.dwSynt + (iCount / 2)) / iCount; #endif // } DETAILED_DECODE_TIMINGS_ON
/* Output the average information
*/ fprintf(pFile,"Average over %d frames\n", iCount); OutputDecTimingDetail(pFile, &dtiTemp); }
fclose(pFile); done:
return; }
void OutputDecTimingDetail(FILE * pFile, DEC_TIMING_INFO * pDecTimingInfo) { unsigned long dwOther; unsigned long dwRoundUp; unsigned long dwDivisor;
fprintf(pFile, "\tDecode = %10u (%d milliseconds at 166Mhz)\n", pDecTimingInfo->dwDecode, (pDecTimingInfo->dwDecode + 83000) / 166000); dwOther = pDecTimingInfo->dwDecode; #ifdef DETAILED_DECODE_TIMINGS_ON // { DETAILED_DECODE_TIMINGS_ON
/* This is needed because of the integer truncation.
*/ dwDivisor = pDecTimingInfo->dwDecode / 100; // to yield a percent
dwRoundUp = dwDivisor / 2; if (dwDivisor) { fprintf(pFile, "\tLine_Unpk = %10u (%2d%%)\n", pDecTimingInfo->dwLine_Unpk, (pDecTimingInfo->dwLine_Unpk + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwLine_Unpk; fprintf(pFile, "\tLsp_Inq = %10u (%2d%%)\n", pDecTimingInfo->dwLsp_Inq, (pDecTimingInfo->dwLsp_Inq + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwLsp_Inq; fprintf(pFile, "\tLsp_Int = %10u (%2d%%)\n", pDecTimingInfo->dwLsp_Int, (pDecTimingInfo->dwLsp_Int + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwLsp_Int; fprintf(pFile, "\tVariousD = %10u (%2d%%)\n", pDecTimingInfo->dwVariousD, (pDecTimingInfo->dwVariousD + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwVariousD; fprintf(pFile, "\tFcbk_UnpkD = %10u (%2d%%)\n", pDecTimingInfo->dwFcbk_UnpkD, (pDecTimingInfo->dwFcbk_UnpkD + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwFcbk_UnpkD; fprintf(pFile, "\tDecod_AcbkD = %10u (%2d%%)\n", pDecTimingInfo->dwDecod_AcbkD, (pDecTimingInfo->dwDecod_AcbkD + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwDecod_AcbkD; fprintf(pFile, "\tComp_Info = %10u (%2d%%)\n", pDecTimingInfo->dwComp_Info, (pDecTimingInfo->dwComp_Info + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwComp_Info; fprintf(pFile, "\tRegen = %10u (%2d%%)\n", pDecTimingInfo->dwRegen, (pDecTimingInfo->dwRegen + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwRegen; fprintf(pFile, "\tSynt = %10u (%2d%%)\n", pDecTimingInfo->dwSynt, (pDecTimingInfo->dwSynt + dwRoundUp) / dwDivisor); dwOther -= pDecTimingInfo->dwSynt; fprintf(pFile, "\tOther = %10u (%2d%%)\n", dwOther, (dwOther + dwRoundUp) / dwDivisor); } #endif // } DETAILED_DECODE_TIMINGS_ON
} #endif // { LOG_DECODE_TIMINGS_ON
|