sigproc.c

来自「speech signal process tools」· C语言 代码 · 共 631 行 · 第 1/2 页

C
631
字号
/* * This material contains unpublished, proprietary software of  * Entropic Research Laboratory, Inc. Any reproduction, distribution,  * or publication of this work must be authorized in writing by Entropic  * Research Laboratory, Inc., and must bear the notice:  * *    "Copyright (c) 1990-1996 Entropic Research Laboratory, Inc.  *                   All rights reserved" * * The copyright notice above does not evidence any actual or intended  * publication of this source code.      * * Written by:  David Talkin * Checked by: * Revised by:  Derek Lin, David Talkin * * Brief description: *     A collection of pretty generic signal-processing routines. * * */static char *sccs_id = "@(#)sigproc.c	1.4	9/9/96	ERL";#include <math.h>#include <malloc.h>#include <esps/esps.h>#include "f0.h"#include "f0_structs.h"/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Return a time-weighting window of type type and length n in dout. * Dout is assumed to be at least n elements long.  Type is decoded in * the switch statement below. */int get_window(dout, n, type)     register float *dout;     register int n, type;{  static float *din = NULL;  static int n0 = 0;  float preemp = 0.0;  if(n > n0) {    register float *p;    register int i;        if(din) free(din);    din = NULL;    if(!(din = (float*)malloc(sizeof(float)*n))) {      Fprintf(stderr,"Allocation problems in get_window()\n");      return(FALSE);    }    for(i=0, p=din; i++ < n; ) *p++ = 1;    n0 = n;  }  return(window(din, dout, n, preemp, type));}  /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Apply a rectangular window (i.e. none).  Optionally, preemphasize. */void rwindow(din, dout, n, preemp)     register float *din;     register float *dout, preemp;     register int n;{  register float *p; /* If preemphasis is to be performed,  this assumes that there are n+1 valid   samples in the input buffer (din). */  if(preemp != 0.0) {    for( p=din+1; n-- > 0; )      *dout++ = (float)(*p++) - (preemp * *din++);  } else {    for( ; n-- > 0; )      *dout++ =  *din++;  }}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Generate a cos^4 window, if one does not already exist. */void cwindow(din, dout, n, preemp)     register float *din;     register float *dout, preemp;     register int n;{  register int i;  register float *p;  static int wsize = 0;  static float *wind=NULL;  register float *q, co;   if(wsize != n) {		/* Need to create a new cos**4 window? */    register double arg, half=0.5;        if(wind) wind = (float*)realloc(wind,n*sizeof(float));    else wind = (float*)malloc(n*sizeof(float));    wsize = n;    for(i=0, arg=3.1415927*2.0/(wsize), q=wind; i < n; ) {      co = half*(1.0 - cos((half + (double)i++) * arg));      *q++ = co * co * co * co;    }  }/* If preemphasis is to be performed,  this assumes that there are n+1 valid   samples in the input buffer (din). */  if(preemp != 0.0) {    for(i=n, p=din+1, q=wind; i--; )      *dout++ = *q++ * ((float)(*p++) - (preemp * *din++));  } else {    for(i=n, q=wind; i--; )      *dout++ = *q++ * *din++;  }}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Generate a Hamming window, if one does not already exist. */void hwindow(din, dout, n, preemp)     register float *din;     register float *dout, preemp;     register int n;{  register int i;  register float *p;  static int wsize = 0;  static float *wind=NULL;  register float *q;  if(wsize != n) {		/* Need to create a new Hamming window? */    register double arg, half=0.5;        if(wind) wind = (float*)realloc(wind,n*sizeof(float));    else wind = (float*)malloc(n*sizeof(float));    wsize = n;    for(i=0, arg=3.1415927*2.0/(wsize), q=wind; i < n; )      *q++ = (.54 - .46 * cos((half + (double)i++) * arg));  }/* If preemphasis is to be performed,  this assumes that there are n+1 valid   samples in the input buffer (din). */  if(preemp != 0.0) {    for(i=n, p=din+1, q=wind; i--; )      *dout++ = *q++ * ((float)(*p++) - (preemp * *din++));  } else {    for(i=n, q=wind; i--; )      *dout++ = *q++ * *din++;  }}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Generate a Hanning window, if one does not already exist. */void hnwindow(din, dout, n, preemp)     register float *din;     register float *dout, preemp;     register int n;{  register int i;  register float *p;  static int wsize = 0;  static float *wind=NULL;  register float *q;  if(wsize != n) {		/* Need to create a new Hanning window? */    register double arg, half=0.5;        if(wind) wind = (float*)realloc(wind,n*sizeof(float));    else wind = (float*)malloc(n*sizeof(float));    wsize = n;    for(i=0, arg=3.1415927*2.0/(wsize), q=wind; i < n; )      *q++ = (half - half * cos((half + (double)i++) * arg));  }/* If preemphasis is to be performed,  this assumes that there are n+1 valid   samples in the input buffer (din). */  if(preemp != 0.0) {    for(i=n, p=din+1, q=wind; i--; )      *dout++ = *q++ * ((float)(*p++) - (preemp * *din++));  } else {    for(i=n, q=wind; i--; )      *dout++ = *q++ * *din++;  }}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Apply a window of type type to the short PCM sequence of length n * in din.  Return the floating-point result sequence in dout.  If preemp * is non-zero, apply preemphasis to tha data as it is windowed. */int window(din, dout, n, preemp, type)     register float *din;     register float *dout, preemp;     register int n;     int type;{  switch(type) {  case 0:			/* rectangular */    rwindow(din, dout, n, preemp);    break;  case 1:			/* Hamming */    hwindow(din, dout, n, preemp);    break;  case 2:			/* cos^4 */    cwindow(din, dout, n, preemp);    break;  case 3:			/* Hanning */    hnwindow(din, dout, n, preemp);    break;  default:    Fprintf(stderr,"Unknown window type (%d) requested in window()\n",type);    return(FALSE);  }  return(TRUE);}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Compute the pp+1 autocorrelation lags of the windowsize samples in s. * Return the normalized autocorrelation coefficients in r. * The rms is returned in e. */void autoc( windowsize, s, p, r, e )     register int p, windowsize;     register float *s, *e;     register float *r;{  register int i, j;  register float *q, *t, sum, sum0;  for( i=windowsize, q=s, sum0=0.0; i--;) {    sum = *q++;    sum0 += sum*sum;  }  *r = 1.;			/* r[0] will always =1. */  if(sum0 == 0.0) {		/* No energy: fake low-energy white noise. */    *e = 1.;			/* Arbitrarily assign 1 to rms. */    /* Now fake autocorrelation of white noise. */    for ( i=1; i<=p; i++){      r[i] = 0.;    }    return;  }  *e = sqrt((double)(sum0/windowsize));  sum0 = 1.0/sum0;  for( i=1; i <= p; i++){    for( sum=0.0, j=windowsize-i, q=s, t=s+i; j--; )      sum += (*q++) * (*t++);    *(++r) = sum*sum0;  }}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Using Durbin's recursion, convert the autocorrelation sequence in r * to reflection coefficients in k and predictor coefficients in a. * The prediction error energy (gain) is left in *ex. * Note: durbin returns the coefficients in normal sign format. *	(i.e. a[0] is assumed to be = +1.) */void durbin ( r, k, a, p, ex)     register int p;			/* analysis order */     register float *r, *k, *a, *ex;{  float  bb[BIGSORD];  register int i, j;  register float e, s, *b = bb;  e = *r;  *k = -r[1]/e;  *a = *k;  e *= (1. - (*k) * (*k));  for ( i=1; i < p; i++){    s = 0;    for ( j=0; j<i; j++){      s -= a[j] * r[i-j];    }    k[i] = ( s - r[i+1] )/e;    a[i] = k[i];    for ( j=0; j<=i; j++){      b[j] = a[j];    }    for ( j=0; j<i; j++){      a[j] += k[i] * b[i-j-1];    }    e *= ( 1. - (k[i] * k[i]) );  }  *ex = e;}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//*  Compute the autocorrelations of the p LP coefficients in a.  *  (a[0] is assumed to be = 1 and not explicitely accessed.) *  The magnitude of a is returned in c. *  2* the other autocorrelation coefficients are returned in b. */void a_to_aca ( a, b, c, p )float *a, *b, *c;register int p;{  register float  s, *ap, *a0;  register int  i, j;  for ( s=1., ap=a, i = p; i--; ap++ )    s += *ap * *ap;  *c = s;  for ( i = 1; i <= p; i++){    s = a[i-1];    for (a0 = a, ap = a+i, j = p-i; j--; )      s += (*a0++ * *ap++);    *b++ = 2. * s;  }}/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*//* Compute the Itakura LPC distance between the model represented * by the signal autocorrelation (r) and its residual (gain) and * the model represented by an LPC autocorrelation (c, b). * Both models are of order p. * r is assumed normalized and r[0]=1 is not explicitely accessed. * Values returned by the function are >= 1.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?