📄 cgain.c
字号:
/*************************************************************************** ROUTINE* cgain** FUNCTION* Find codeword gain and error (TERNARY CODE BOOK ASSUMED!)** SYNOPSIS* function cgain(ex, l, first, len, match)** formal** data I/O* name type type function* -------------------------------------------------------------------* ex[l] float i excitation vector (ternary codeword)* l int i size of ex (dimension of codeword)* first int i first call flag* len int i length to truncate impulse response* match float o negative partial squared error* cgain float fun optimal gain for ex** external* data I/O* name type type function* -------------------------------------------------------------------* e0[] float i* h[]; float i***************************************************************************** DESCRIPTION** Find the gain and error for each code word:* 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: Code words 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 inpulse 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 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!):**#define j 10** DSP chip instructions/operations:* int MUL=1; !multiply* int ADD=1; !add* int SUB=1; !subtract* int MAC=1; !multiply & accumulate* int MAD=2; !multiply & add* int CMP=1; !compare** CELP algorithm parameters:* int L=60; !subframe length* int len=30; !length to truncate calculations (<= L)* int K=4; !number of subframes/frame* int shift=2; !shift between code words* int g_bits=5; !cbgain bit allocation* float p=0.77; !code book sparsity* float F=30.e-3; !time (seconds)/frame** int N[j] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512};** main()* {* int i;* float C, R, E, G, IPS;* printf("\n N C R E G MIPS\n");* for (i = 0; i < j; i++)* {* C = (335)*MAD + (N[i]-1)*shift*(1.0-p)*len*ADD;* R = N[i]*L*MAC;* E = L*MAC + (N[i]-1)*((1.0-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;* printf(" %4d %f %f %f %f %f\n", 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);* }* }** N C R E G MIPS* 1 0.089333 0.008000 0.008000 0.002533 0.107867* 2 0.091173 0.016000 0.011573 0.005067 0.123813* 4 0.094853 0.032000 0.018719 0.010133 0.155706* 8 0.102213 0.064000 0.033011 0.020267 0.219491* 16 0.116933 0.128000 0.061595 0.040533 0.347062* 32 0.146373 0.256000 0.118763 0.081067 0.602203* 64 0.205253 0.512000 0.233100 0.162133 1.112486* 128 0.323013 1.024000 0.461773 0.324267 2.133053* 256 0.558533 2.048000 0.919118 0.648533 4.174185* 512 1.029573 4.096000 1.833810 1.297067 8.256450***************************************************************************** CALLED BY** cbsearch** CALLS** gainencode2****************************************************************************** REFERENCES** Tremain, Thomas E., Joseph P. Campbell, Jr and Vanoy C. Welch,* "A 4.8 kbps Code Excited Linear Predictive Coder," Proceedings* of the Mobile Satellite Conference, 3-5 May 1988, pp. 491-496.** Campbell, Joseph P. Jr., Vanoy C. Welch and Thomas E. Tremain,* "The New 4800 bps Voice Coding Standard," Military and * Government Speech Tech, 1989, p. 64-70.** 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***************************************************************************/#include <math.h>#include "ccsub.h"extern float e0[MAXLP], h[MAXLP];floatcgain(ex, l, first, len, match)int l, first, len;float ex[], *match;{ register float cor; float cgain, gainencode2(); static float y[MAXL], y59save, y60save, eng; int i, j; if (first) { /** 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, len-1) y = SUM ex * h , where i = 0, ..., L-1 points i+j, t j=0 i j ex |0 1 . . . L-1| h |x x len-1...1 0| = y[0] h |x x len-1...1 0| = y[1] : : h |x x len-1...1 0| = y[L-1] ----------------------------------------------------- */ for (i = 0; i < l; i++) y[i] = 0.0; for (i = 0; i < l; i++) { if (nint(ex[i]) != 0.0) for(j = 0; j < l-i && j < len; j++) y[i+j] += ex[i]*h[j]; } } else { /** 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 = 0, ..., L-1 points i, m i-1, m-1 -m i and m = 0, ..., cbsize-1 code words NOTE: The data movements in the 2 loops with "y[i] = y[i - 1]" 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. ----------------------------------------------------- */ /* *First shift */ if (nint(ex[1]) != 0) { /* *ternary stochastic code book (-1, 0, +1) */ if (nint(ex[1]) == 1) for (i = len - 1; i > 0; i--) y[i - 1] += h[i]; else for (i = len - 1; i > 0; i--) y[i - 1] -= h[i]; } for (i = l - 1; i > 0; i--) y[i] = y[i - 1]; y[0] = ex[1] * h[0]; /* *Second shift */ if (nint(ex[0]) != 0) { /* *ternary stochastic code book (-1, 0, +1) */ if (nint(ex[0]) == 1) for (i = len - 1; i > 0; i--) y[i - 1] += h[i]; else for (i = len - 1; i > 0; i--) y[i - 1] -= h[i]; } for (i = l - 1; i > 0; i--) y[i] = y[i - 1]; y[0] = ex[0] * h[0]; } /** 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? */ cor = 0.0; for (i = 0; i < l; i++) { cor += y[i] * e0[i]; } /* *End correct energy on subsequent code words: */ if (nint(ex[0]) == 0 && nint(ex[1]) == 0 && !first) eng = eng - y59save * y59save - y60save * y60save; else { eng = 0.0; for (i = 0; i < l; i++) eng += y[i] * y[i]; } y59save = y[l - 2]; y60save = y[l - 1]; /* Compute gain and error: NOTE: Actual MSPE = e0.e0 - cgain(2*cor-cgain*eng) since e0.e0 is independent of the code word, minimizing MSPE is equivalent to maximizing: *match = cgain(2*cor-cgain*eng) If unquantized cgain is used, this simplifies: *match = cor*cgain */ /* Independent (open-loop) quantization of gain and match (index): */ if (eng <= 0.0) eng = 1.0; cgain = cor / eng; *match = cor * cgain; /* *Joint (closed-loop) quantization of gain and match (index): */ /* *(Beware that the match score can be negative!) */ /* cgain = gainencode2(cor, eng, &i); */ /* *match = cgain * (2.0 * cor - cgain * eng); */ return (cgain);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -