FE_lpcc.cpp
上传用户:italyroyal
上传日期:2013-05-06
资源大小:473k
文件大小:11k
源码类别:

语音合成与识别

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // This is a part of the Feature program.
  3. // Version: 1.0
  4. // Date: February 22, 2003
  5. // Programmer: Oh-Wook Kwon
  6. // Copyright(c) 2003 Oh-Wook Kwon. All rights reserved. owkwon@ucsd.edu
  7. ///////////////////////////////////////////////////////////////////////////////
  8. /****************************************************************
  9. LPC cepstral analysis
  10. Original: Communications Research Lab.(CRL),
  11.   Dept. of Electrical Eng., KAIST.
  12.   (contributors : Y. K. Park, O. W. Kwon)
  13. Modified by I. J. Choi, Feb. 5, 1996
  14. Modified by O. W. Kwon, Feb. 22, 1998
  15. *************************************************************************/
  16. #include "StdAfx.h"
  17. #include "FE_feature.h"
  18. /* 
  19. Computes LPC and cepstrum coefficients by using the auto-correlation or covariance method 
  20. */
  21. /*
  22. lpc_cep[0] = log(G)
  23. lpc_cep[i] = c[i], i=1,...,N
  24. */
  25. int Fe::lpc_cepstrum_basic(short *sample, int frameSize, float *lpc_cep, int ceporder, int norder)
  26. {
  27. float G;
  28. vector<float> acf(norder+1);
  29. lpc_basic(sample, frameSize, &acf[0], norder, &G);
  30. lpc_to_cepstrum(&acf[0], norder, lpc_cep, ceporder, G);
  31. cepstral_window(&lpc_cep[0], ceporder, m_lifter);
  32. /* owkwon: To make dynamic range consistent with other kinds of cepstral coefficients */
  33. /* Needs further investigation */
  34. for (int i=0;i<=ceporder;i++) lpc_cep[i] /= 8;
  35. return(1);
  36. }
  37. /* 
  38. Auto-correlation method.
  39. */
  40. /*------------------------------------------------------------------------* * Routine generates the autocorrelation sequence from the input windowed *  * data sequence. It uses 'n' products to compute ac[0], 'nsamp'-1    *  * products to compute ac[1],..., and 'nsamp'-'order' products to compute *  * ac[order]. Note that the length of the array 'ac' should be order+1.   * *------------------------------------------------------------------------*/ int Fe::auto_correlation(float *wsamp, float *ac, int n, int norder) { int  i,j; for (i=0; i<=norder; i++){ ac[i] = 0.0; for (j=i; j<n; j++) ac[i] += wsamp[j]*wsamp[j-i];
  41. ac[i] /= n; /* normalize */ } return(1); }
  42. /************************************************************************ *    modified Levinson algorithm        * ************************************************************************/ int Fe::levins (float *r, float *kcf, float *acf, int norder) { int  j,n;
  43. vector<float> p(norder+1);
  44. vector<float> q(norder+1);
  45. vector<float> acf_tmp(norder+1);
  46. vector<float> a(norder+1);
  47. /* normalize r's to prevent round off error */ if(!normalize_corr(r,norder)) return 1; kcf[1] = acf_tmp[1] = acf[1] = a[1] = r[1]; for(n=2; n<=norder; n++){ for(j=1; j<n; j++){ p[j] = r[n-j] * a[j]; q[j] = r[j] * a[j]; } a[n]=( r[n]-sum(1,n-1,&p[0]) ) / ( r[0]-sum(1,n-1,&q[0]) );   kcf[n] = a[n]; if (fabs(a[n]) >= 1. ) a[n] = 0.; for(j=1; j<n; j++) a[j] = acf_tmp[j] - a[n]*acf_tmp[n-j]; for(j=1; j<=n; j++){ acf_tmp[j] = a[j]; if ( n == norder ) acf[j] = a[j]; } }
  48. return(1); }
  49. /*------------------------------------------------------------------------* * durbin() - solution of the auto-correlation normal equations           * *                                       * * Routine obtains the (forward) predictor coefficients from the auto-    * * correlation or the covariance sequence. As a by-product, it also       * * obtains the reflection coefficients.     * *    * *------------------------------------------------------------------------*/ int Fe::durbin(float *r, float *kcf, float *acf, int norder) { int  i,j; float  sum,error; vector<float> b(norder+1);
  50. /* initialize predictor coeffs. */ acf[0] = 1.0; for(i=1; i<=norder; i++) acf[i]=0.0; /* normalize autocorrs */ if(!normalize_corr(r,norder)) return 1; /* durbin's recursion */ for(error = r[0], i = 1; i <= norder; i++) { for(sum = r[i], j=1; j < i; j++) sum -= acf[j] * r[i - j]; acf[i] = kcf[i] = sum / error; for(j = 1; j < i; j++) b[j] = acf[i - j]; for(j = 1; j < i; j++) acf[j] -= kcf[i] * b[j]; error = (1 - kcf[i] * kcf[i]) * error; } 
  51. return 1; }
  52. int Fe::stable_k(float *kcf, int norder)  { int  i,j; for(i=1; i<=norder; i++){ if (fabs(kcf[i]) >= 1) for(j=1;j<=norder;j++) kcf[j]=kcf[j]*power((float)0.99,j);
  53. } return(1); }
  54. /*------------------------------------------------------------------------* *  normalize r's to prevent round off error   *------------------------------------------------------------------------*/ int Fe::normalize_corr(float *r, int norder) { int i;
  55. if(r[0] == (float)0) return 0; for(i=1; i<=norder; i++) r[i] /= r[0];
  56. r[0] = 1;
  57. return 1; }
  58. /* 
  59. Covariance method
  60. */
  61. /*
  62. Calculates an autocorrelation matrix by the covariance matrix.
  63. */
  64. int Fe::covariance(float *sample, int frameSize, FeMatrix<float>& cov, int norder)
  65. {
  66.     int i,j,n;
  67. for (i=0; i<=norder; i++) {
  68. for (j=0; j<=norder; j++) {
  69. float x,y;
  70. cov[i][j] = 0.0;
  71. for (n=0; n<frameSize; n++){
  72. x = (n-i >= 0 && n-i < frameSize) ? sample[n-i] : 0;
  73. y = (n-j >= 0 && n-j < frameSize) ? sample[n-j] : 0;
  74. cov[i][j] += x*y;
  75. }
  76. }
  77. }
  78. return(1);
  79. }
  80. /* 
  81. Ref: W. H. Press, S. A. Teukolsky, W. T. Vetterling, and B. P. Flannery, 
  82. Numerical Recipes in C, 2ed. pp. 96-98, 1992.
  83. */
  84. /*
  85. Given a positive-difinite symmetric matrix a[0..n-1][0..n-1], this routine constructs its
  86. Cholesky decomposition, A = L.L'. On input, only the upper triangle of a need be given;
  87. it is not modified. The Cholesky factor L is returned in the lower triangle of a,
  88. except for its diagonal elements which are returned in p[0..n-1].
  89. */
  90. int Fe::choldc(FeMatrix<float>& a, int n, float *p)
  91. {
  92. int i,j,k;
  93. for(i=0;i<n;i++){
  94. for(j=i;j<n;j++){
  95. float sum=a[i][j];
  96. for(k=i-1;k>=0;k--) sum -= a[i][k]*a[j][k];
  97. if(i==j){
  98. if(sum <= 0.0) return FALSE; // a, with rounding errors, is not positive definite.
  99. p[i] = sqrt(sum);
  100. }
  101. else a[j][i] = sum/p[i];
  102. }
  103. }
  104. return TRUE;
  105. }
  106. /* 
  107. Solves the n linear equations A.x = b, where a is a positive-definite symmetric matrix.
  108. a[0..n-1][0..n-1] and p[0..n-1] are input as the output of the routine choldc. Only the lower triangle of a is accessed.
  109. b[0..n-1] is input as the right-hand side vector. The solution vector is returned
  110. in x[0..n-1]. a, n, and p are not modified and can be left in place for successive calls
  111. with different right-hand sides b. b is not modified unless you identify b and x in the calling sequence,
  112. which is allowed. 
  113. */
  114. int Fe::cholsl(FeMatrix<float>& a, int n, float *p, float *b, float *x)
  115. {
  116. int i,k;
  117. float sum;
  118. // solve L.y = b, storing y in x.
  119. for(i=0;i<n;i++){
  120. for(sum=b[i],k=i-1;k>=0;k--) sum -= a[i][k]*x[k];
  121. x[i] = sum/p[i];
  122. }
  123. // solve L'.x = y.
  124. for(i=n-1;i>=0;i--){
  125. for(sum=x[i],k=i+1;k<n;k++) sum -= a[k][i]*x[k];
  126. x[i] = sum/p[i];
  127. }
  128. return TRUE;
  129. }
  130. /* Solves A.x = b. */
  131. int Fe::CholeskySol(FeMatrix<float>& a, float *b, float *x, int n)
  132. {
  133. vector<float> p(n);
  134. int success = choldc(a, n, &p[0]);
  135. if(success) cholsl(a, n, &p[0], b, x);
  136. return success;
  137. }
  138. int Fe::lpc_cov(float *sample, int frameSize, FeMatrix<float>& cov, float *acf, int norder, float *G)
  139. {
  140. int i; covariance(sample, frameSize, cov, norder);
  141. FeMatrix<float> phi(norder, norder);
  142. vector<float> psi(norder);
  143. for(i=1;i<=norder;i++){
  144. psi[i-1] = cov[i][0];
  145. for(int j=1;j<=norder;j++){
  146. phi[i-1][j-1] = cov[i][j];
  147. }
  148. }
  149. vector<float> rorg(norder+1);
  150. for(i=0;i<=norder;i++) rorg[i] = cov[i][0];
  151. // Solves phi.a = psi.
  152. int success = CholeskySol(phi, &psi[0], acf+1, norder);
  153. if(!success){
  154. for(i=1;i<=norder;i++) acf[i] = 0;
  155. }
  156. /* G denotes LPC gain G */
  157. acf[0] = 1;
  158. if(G) (*G) = calc_lpc_gain_basic(&rorg[0], acf, norder);
  159. return success;
  160. }
  161. int Fe::lpc_cov_error(float *sample, int frameSize, float *acf, int norder, float* residual)
  162. {
  163. int i,n;
  164. for(n=0;n<frameSize;n++){
  165. float si;
  166. residual[n] = (n>=0 && n<frameSize) ? sample[n] : 0;
  167. for(i=1;i<=norder;i++){
  168. si = (n-i>=0 && n-i<frameSize) ? sample[n-i] : 0;
  169. residual[n] -= acf[i]*si;
  170. }
  171. }
  172. return(1);
  173. }
  174. /************************************************************************
  175.   This subroutine computes the cepstral coefficients
  176.     cep[1]-cep[ncf] cepstrum coefficients from the predictor coefficients
  177.     acf[1]-acf[norder] predictor coefficients
  178.     norder is the order of the LPC model.
  179.   Equations:
  180.     c(0) = log (G)
  181.     c(n) = a(n) + 1/n * sum_{k=1}^{n-1} k c(k) a(n-k)    for n <= norder
  182.     c(n) = 1/n * sum_{k=n-p}^{n-1} k/n c(k) a(n-k)         for n > norder
  183.   Note that the definition of a[] is 
  184.   y(n) = a(1)y(n-1) + a(2)y(n-2) + ...
  185.   [1] Papamichalis, P.E. Practical Approaches to Speech Coding. Prentice Hall, Englewood Cliffs, NJ, 1987
  186.   [2] Rabiner, L.R. and Juang B.H. Fundamentals of Speech Recognition. Prentice Hall, Englewood Cliffs, NJ, 1993 
  187. *************************************************************************/
  188. int Fe::lpc_to_cepstrum(float *acf, int norder, float *cep, int ncf, float G)
  189. {
  190. int n,k;
  191. cep[0] = LogE(G);
  192. for (n = 1; n <= ncf; n++){
  193. float sum=0;
  194. if(n <= norder){
  195. for (k=1; k <= n-1; k++) sum += k*cep[k]*acf[n-k];
  196. cep[n] = acf[n] + 1/(float)n*sum;
  197. }
  198. else{
  199. for (k=n-norder; k <= n-1; k++) sum += k*cep[k]*acf[n-k];
  200. cep[n] = 1/(float)n*sum;
  201. }
  202. }
  203. return(1);
  204. }
  205. /********************************************************************
  206.  BILINEAR TRANSFORM
  207.  REF) A. V. Oppenheim, D. H. Johnson, "Discrete
  208.  Representation of Signals", Proc. of IEEE,
  209.  Vol. 60, No. 6, June, 1972, pp. 681-691.
  210.  
  211.   Comment) This bilinear transform maintains the form of the  spectrum
  212.   for a discrete-time signal but transforms the frequency axis
  213.   in a nonlinear manner.
  214.   
  215.    Original sequence ( F[n] ) ===> Transformed sequence ( G[k,n] )
  216.    Designed digital filter
  217.    i.e
  218.    G[k] = { sum from n=0 to infinity } F[n] * H[k,n]
  219.    
  220. Time and Frequency update equations:
  221.      G[0,n] = a * G[0][n-1] + F[-n]
  222.  G[1,n] = a * G[1][n-1] + G[0][n-1]
  223.  
  224.   G[k][n] = a * ( G[k][n-1] - G[k-1][n] ) + G[k-1][n-1] 
  225.   for k = 2, 3, ...
  226. *********************************************************************/
  227. int Fe::bilinear_transform(float *org_seq, int num_org_seq, float *trans_seq, int no_update, float warp_coeff ) 
  228. {
  229. int  n, k;
  230. vector<vector<float> > G; /* G is no_update x num_org_seq matrix. */
  231. assert(no_update>2);
  232. G.resize(no_update);
  233. for(k=0;k<no_update;k++) G[k].resize(num_org_seq);
  234. /*  Compute G[0][n] & G[1][n] */
  235. G[0][num_org_seq-1] = org_seq[num_org_seq-1];
  236. for( n = num_org_seq-2 ; n >= 0 ; n-- ) {
  237. G[0][n] = warp_coeff * G[0][n+1] + org_seq[n];
  238. }
  239. G[1][num_org_seq - 1] = 0.0;
  240. for( n = num_org_seq-2 ; n >= 0 ; n-- )
  241. G[1][n] = warp_coeff * G[1][n+1] +
  242. ((float)1.0 - warp_coeff * warp_coeff ) * G[0][n+1];
  243. /* Compute G[k][n] */
  244. for( k = 2 ; k < no_update ; k++ ) {
  245. /* Initialize G[k][num_org_seq-1] */
  246. G[k][num_org_seq-1] = (float)(-1.0)*warp_coeff*G[k-1][num_org_seq-1];
  247. for( n = num_org_seq-2 ; n >= 0 ; n-- )
  248. G[k][n]=warp_coeff*( G[k][n+1]-G[k-1][n])+G[k-1][n+1];
  249. } /* end of k-loop */
  250. /* Return Transformed Sequence */
  251. for( k = 0 ; k < no_update ; k++ ) trans_seq[k] = G[k][0];
  252. return(1);
  253. }