📄 conv_cor.c
字号:
/*LINTLIBRARY*/ /*PROTOLIB1*/#include <math.h>#include "main.h"#include "conv_cor.h"#include "rint.h"static void CalcStochConv(float ExcVec[],int ExVecLen,float LPImpResp[],int LenTruncH,float Conv[MAX_CW_VEC_LEN]);static void EndCorrectStoch(float ExcVal,float LPImpResp[],int LenTruncH,float Conv[]);static void CalcCorEngStoch(float Residual[RES_LEN],float Conv[],float ExcVal1,float ExcVal2,int First,float *Cor,float *Energy);static void CompGainErrStoch(float Energy,float Cor,float *Gain,float *Error);/**************************************************************************** ROUTINE* ConvCor** FUNCTION* Find codeword gain and error (TERNARY CODE BOOK ASSUMED!)** SYNOPSIS* ConvCor(ExcVec, ExVecLen, First, LPImpResp, LenTruncH, NegErr)** formal ** data I/O* name type type function* -------------------------------------------------------------------* ExcVec float i excitation vector (ternary codeword)* ExcVecLen int i size of ex (dimension of codeword)* First int i first call flag* LPImpResp float i LPC Impulse Response* LenTruncH int i Length to truncate impulse response* NegErr float o negative partial squared error** ConvCor float fun optimal gain for ex***==========================================================================* * DESCRIPTION** (The calculations below may be valid for version 3.2, but may not be * correct for version 3.3).** For each code word find its gain and error:* a. Filter code words through impulse response* of perceptual weighting filter (LPC filter with* bandwidth broadening).* b. Correlate filtered result with actual second error* signal (e0).* c. Compute MSPE gain and error for code book vector.** Notes: Codewords may contain many zeros (i.e., ex(1)=0). The* code book could be accessed by a pointer to nonzero samples.* Because the code book is static, it`s silly to test its* samples as in the code below.** Proper selection of the convolution length (len) depends on* the perceptual weighting filter's expansion factor (gamma)* which controls the damping of the impulse response.** This is one of CELP's most computationally intensive* routines. Neglecting overhead, the approximate number of* DSP instructions (add, multiply, multiply accumulate, or* compare) per second (IPS) is:** Code book size MIPS* -------------- ----* 64 1.1* 128 2.1* 256 4.2* 512 (max) 8.3** C: convolution (recursive truncated end-point correction)* R: correlation* E: energy (recursive end-point correction)* G: gain quantization** celp code book search complexity (doesn't fully exploit ternary values!):* implicit undefined(a-z)cc DSP chip instructions/operation:* integer MUL, ADD, SUB, MAC, MAD, CMP* parameter (MUL=1) !multiply* parameter (ADD=1) !add* parameter (SUB=1) !subtract* parameter (MAC=1) !multiply & accumulate* parameter (MAD=2) !multiply & add* parameter (CMP=1) !comparecc CELP algorithm parameters:* integer L, len, K, shift, g_bits* real p, F* parameter (L=60) !subframe length* parameter (len=30) !length to truncate calculations (<= L)* parameter (p=0.77) !code book sparsity* parameter (shift=2) !shift between code words* parameter (K=4) !number of subframes/frame* parameter (F=30.e-3) !time (seconds)/frame* parameter (g_bits=5) !cbgain bit allocationc* integer j* parameter (j=10)* integer N(j), i* real C, R, E, G, IPS* data N/1, 2, 4, 8, 16, 32, 64, 128, 256, 512/* print 1*1 format(10x,'N',10x,'C',13x,'R',12x,'E',15x,'G',13x,'MIPS')* do i = 1, j* C = (335)*MAD + (N(i)-1)*shift*(1.-p)*len*ADD* R = N(i)*L*MAC* E = L*MAC + (N(i)-1)*((1.-p*p)*L*MAC + (p*p)*2*MAD)* G = N(i)*(g_bits*(CMP+MUL+ADD) + 3*MUL+1*SUB)* IPS = (C+R+E+G)*K/F* print *,N(i),C*K/1.e6/F,R*K/1.e6/F,E*K/1.e6/F,G*K/1.e6/F,IPS/1.e6* end do* end** N C R E G MIPS* 1 8.9333333E-02 8.0000004E-03 8.0000004E-03 2.5333334E-03 0.1078667 * 2 9.1173328E-02 1.6000001E-02 1.1573013E-02 5.0666668E-03 0.1238130 * 4 9.4853334E-02 3.2000002E-02 1.8719040E-02 1.0133334E-02 0.1557057 * 8 0.1022133 6.4000003E-02 3.3011094E-02 2.0266667E-02 0.2194911 * 16 0.1169333 0.1280000 6.1595201E-02 4.0533334E-02 0.3470618 * 32 0.1463733 0.2560000 0.1187634 8.1066668E-02 0.6022034 * 64 0.2052534 0.5120000 0.2330998 0.1621333 1.112487 * 128 0.3230133 1.024000 0.4617727 0.3242667 2.133053 * 256 0.5585334 2.048000 0.9191184 0.6485333 4.174185 * 512 1.029573 4.096000 1.833810 1.297067 8.256450 **==========================================================================** CALLED BY** cbsearch** CALLS** gainencode2**==========================================================================** REFERENCES** See REFERENCES in celp.c...and:** Lin, Daniel, "New Approaches to Stochastic Coding of Speech* Sources at Very Low Bit Rates," Signal Processing III: Theories* and Applications (Proceedings of EUSIPCO-86), 1986, p.445.** Xydeas, C.S., M.A. Ireton and D.K. Baghbadrani, "Theory and* Real Time Implementation of a CELP Coder at 4.8 and 6.0 kbits/s* Using Ternary Code Excitation," Fifth International Conference on* Digital Processing of Signals in Communications, 1988, p. 167.** Ess, Mike, "Simple Convolution on the Cray X-MP,"* Supercomputer, March 1988, p. 35** Supercomputer, July 1988, p. 24****************************************************************************/float ConvCor(float ExcVec[],int ExVecLen,int First,float LPImpResp[SF_LEN],int LenTruncH,float Residual[RES_LEN],float *NegErr){static float Conv[MAX_CW_VEC_LEN];static float Energy=0.0;float Cor;float Gain; if (First) {/* For first codeword, calculate and save convolution of codeword with truncated impulse response */ CalcStochConv(ExcVec, ExVecLen, LPImpResp, LenTruncH, Conv); } else { /* End correct the convolution sum on subsequent code words *//* First Shift */ EndCorrectStoch(ExcVec[1], LPImpResp, LenTruncH, Conv);/* Second Shift */ EndCorrectStoch(ExcVec[0], LPImpResp, LenTruncH, Conv); }/* Calculate correlation and energy */ CalcCorEngStoch(Residual, Conv, ExcVec[0], ExcVec[1], First, &Cor, &Energy);/* Compute Gain and Error */ CompGainErrStoch(Energy, Cor, &Gain, NegErr); return Gain;}/**************************************************************************** ROUTINE* CalcStochConv** FUNCTION* Calculate and save convolution of codeword with * truncated impulse response** SYNOPSIS* CalcStochConv(ExcVec, ExcVecLen, LPImpulseResponse, Conv)** formal ** data I/O* name type type function* -------------------------------------------------------------------* ExcVec float i excitation vector (ternary codeword)* ExcVecLen int i excitation vector length* LPImpResp float i LPC Impulse Response* LenTruncH int i length to truncate impulse response* Conv float o Convolution of codeword with impulse* response***************************************************************************** For first code word, calculate and save convolution* of code word with truncated (to len) impulse response:** NOTES: A standard convolution of two L point sequences* produces 2L-1 points, however, this convolution* generates only the first L points.** A "scalar times vector accumulation" method is used* to exploit (skip) zero samples of the code words:** min(L-i+1, len)* y = SUM ex * h , where i = 1, ..., L points* i+j-1, t j=1 i j** ex |1 2 . . . L|* h |x x len ... 2 1| = y(1)* h |x x len ... 2 1| = y(2)* : :* h |x x len ... 2 1| = y(L)****************************************************************************/void CalcStochConv(float ExcVec[],int ExcVecLen,float LPImpResp[],int LenTruncH,float Conv[MAX_CW_VEC_LEN]){int i, j;/* Initialize */ for(i=0; i< SF_LEN; i++) { Conv[i] = 0.0; } for(i=0; i< ExcVecLen; i++) { if (rint((double)(ExcVec[i])) != 0.0) { for(j=0; j<min(SF_LEN - i, LenTruncH); j++) { Conv[i+j] += ExcVec[i] * LPImpResp[j]; } } }}/**************************************************************************** ROUTINE* EndCorrectStoch** FUNCTION* End correct the convolution sum** SYNOPSIS* EndCorrectStoch(ExcVal, LPImpResp, LenTruncH, Conv)** formal ** data I/O* name type type function* -------------------------------------------------------------------* ExcVal float i Excitation value* LPImpResp float i LPC impulse response* LenTruncH int i Length to truncate impulse response* Conv float o Convolution sum****************************************************************************** End correct the convolution sum on subsequent code words:* (Do two end corrections for a shift by 2 code book)** y = 0* 0, 0* y = y + ex * h where i = 1, ..., L points* i, m i-1, m-1 -m i and m = 1, ..., cbsize-1 code words** NOTE: The data movements in loops "do 59 ..." and "do 69 ..."* are performed many times and can be quite time consuming.* Therefore, special precautions should be taken when* implementing this. Some implementation suggestions:* 1. Circular buffers with pointers to eliminate data moves.* 2. Fast "block move" operation as offered on some DSPs.*****************************************************************************/void EndCorrectStoch(float ExcVal,float LPImpResp[],int LenTruncH,float Conv[]){int i; if(rint((double)(ExcVal)) != 0.0) { /* Ternary stochastic code book (-1, 0, +1) */ if(rint((double)(ExcVal)) == 1.0) { for(i=LenTruncH-1; i>0; i--) { Conv[i-1] += LPImpResp[i]; } } else { for(i=LenTruncH-1; i>0; i--) { Conv[i-1] -= LPImpResp[i]; } } } for(i=SF_LEN-1; i>0; i--) { Conv[i] = Conv[i-1]; } Conv[0] = ExcVal*LPImpResp[0];}/**************************************************************************** ROUTINE* CalcCorEngStoch** FUNCTION* Calculate correlation and energy** SYNOPSIS* CalcCorEngStoch(Residual, Conv, ExcVal1, ExcVal2, First, Cor, Energy)** formal ** data I/O* name type type function* -------------------------------------------------------------------* Residual float i Spectrum and adaptive residual* Conv float i Convolution sum* ExcVal1 float i First excitation vector value* ExcVal2 float i Second excitation vector value* First int i First subframe flag* Cor float o Correlation* Energy float o Energy****************************************************************************** Calculate correlation and energy:* e0 = spectrum & pitch prediction residual* y = error weighting filtered code words** \/\/\/ CELP's computations are focused in this correlation \/\/\/* - For a 512 code book this correlation takes 4 MIPS!* - Decimation?, Down-sample & decimate?, FEC codes?****************************************************************************/void CalcCorEngStoch(float Residual[RES_LEN],float Conv[],float ExcVal1,float ExcVal2,int First,float *Cor,float *Energy){int i;static float NextLastConv=0.0;static float LastConv=0.0;/* Initialize */ *Cor = 0.0;/* Calculate correlation */ for(i=0; i<SF_LEN; i++) { *Cor += Conv[i]*Residual[i]; }/* End correct energy on subsequent code words */ if ((rint((double)(ExcVal1)) == 0.0) && (rint((double)(ExcVal2)) == 0.0) && (!First)) { *Energy -= NextLastConv*NextLastConv + LastConv*LastConv; } else { *Energy = 0.0; for(i=0; i<SF_LEN; i++) { *Energy += Conv[i] * Conv[i]; } } NextLastConv = Conv[SF_LEN-2]; LastConv = Conv[SF_LEN-1];}/**************************************************************************** ROUTINE* CompGainErrStoch** FUNCTION* Compute gain and error** SYNOPSIS* CompGainErrStoch(Energy, Cor, Gain, Error)** formal ** data I/O* name type type function* -------------------------------------------------------------------* Energy float i Energy* Cor float i Correlation* Gain float o Codebook Gain* Error float o Codebook Error****************************************************************************** Compute gain and error:* NOTE: Actual MSPE = e0.e0 - gain(2*cor-gain*eng)* since e0.e0 is independent of the code word,* minimizing MSPE is equivalent to maximizing:* match = gain(2*cor-gain*eng)* If unquantized gain is used, this simplifies:* match = cor*gain** Independent (open-loop) quantization of gain and match (index):****************************************************************************/void CompGainErrStoch(float Energy,float Cor,float *Gain,float *Error){ if(Energy <= 0.0) *Gain = Cor; else *Gain = Cor/Energy; *Error = Cor * *Gain;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -