annotate src/libvorbis-1.3.3/lib/lpc.c @ 124:e3d5853d5918

Current stable PortAudio source
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 18 Oct 2016 13:11:05 +0100
parents 98c1576536ae
children
rev   line source
cannam@86 1 /********************************************************************
cannam@86 2 * *
cannam@86 3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
cannam@86 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
cannam@86 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
cannam@86 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
cannam@86 7 * *
cannam@86 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
cannam@86 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
cannam@86 10 * *
cannam@86 11 ********************************************************************
cannam@86 12
cannam@86 13 function: LPC low level routines
cannam@86 14 last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
cannam@86 15
cannam@86 16 ********************************************************************/
cannam@86 17
cannam@86 18 /* Some of these routines (autocorrelator, LPC coefficient estimator)
cannam@86 19 are derived from code written by Jutta Degener and Carsten Bormann;
cannam@86 20 thus we include their copyright below. The entirety of this file
cannam@86 21 is freely redistributable on the condition that both of these
cannam@86 22 copyright notices are preserved without modification. */
cannam@86 23
cannam@86 24 /* Preserved Copyright: *********************************************/
cannam@86 25
cannam@86 26 /* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
cannam@86 27 Technische Universita"t Berlin
cannam@86 28
cannam@86 29 Any use of this software is permitted provided that this notice is not
cannam@86 30 removed and that neither the authors nor the Technische Universita"t
cannam@86 31 Berlin are deemed to have made any representations as to the
cannam@86 32 suitability of this software for any purpose nor are held responsible
cannam@86 33 for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
cannam@86 34 THIS SOFTWARE.
cannam@86 35
cannam@86 36 As a matter of courtesy, the authors request to be informed about uses
cannam@86 37 this software has found, about bugs in this software, and about any
cannam@86 38 improvements that may be of general interest.
cannam@86 39
cannam@86 40 Berlin, 28.11.1994
cannam@86 41 Jutta Degener
cannam@86 42 Carsten Bormann
cannam@86 43
cannam@86 44 *********************************************************************/
cannam@86 45
cannam@86 46 #include <stdlib.h>
cannam@86 47 #include <string.h>
cannam@86 48 #include <math.h>
cannam@86 49 #include "os.h"
cannam@86 50 #include "smallft.h"
cannam@86 51 #include "lpc.h"
cannam@86 52 #include "scales.h"
cannam@86 53 #include "misc.h"
cannam@86 54
cannam@86 55 /* Autocorrelation LPC coeff generation algorithm invented by
cannam@86 56 N. Levinson in 1947, modified by J. Durbin in 1959. */
cannam@86 57
cannam@86 58 /* Input : n elements of time doamin data
cannam@86 59 Output: m lpc coefficients, excitation energy */
cannam@86 60
cannam@86 61 float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
cannam@86 62 double *aut=alloca(sizeof(*aut)*(m+1));
cannam@86 63 double *lpc=alloca(sizeof(*lpc)*(m));
cannam@86 64 double error;
cannam@86 65 double epsilon;
cannam@86 66 int i,j;
cannam@86 67
cannam@86 68 /* autocorrelation, p+1 lag coefficients */
cannam@86 69 j=m+1;
cannam@86 70 while(j--){
cannam@86 71 double d=0; /* double needed for accumulator depth */
cannam@86 72 for(i=j;i<n;i++)d+=(double)data[i]*data[i-j];
cannam@86 73 aut[j]=d;
cannam@86 74 }
cannam@86 75
cannam@86 76 /* Generate lpc coefficients from autocorr values */
cannam@86 77
cannam@86 78 /* set our noise floor to about -100dB */
cannam@86 79 error=aut[0] * (1. + 1e-10);
cannam@86 80 epsilon=1e-9*aut[0]+1e-10;
cannam@86 81
cannam@86 82 for(i=0;i<m;i++){
cannam@86 83 double r= -aut[i+1];
cannam@86 84
cannam@86 85 if(error<epsilon){
cannam@86 86 memset(lpc+i,0,(m-i)*sizeof(*lpc));
cannam@86 87 goto done;
cannam@86 88 }
cannam@86 89
cannam@86 90 /* Sum up this iteration's reflection coefficient; note that in
cannam@86 91 Vorbis we don't save it. If anyone wants to recycle this code
cannam@86 92 and needs reflection coefficients, save the results of 'r' from
cannam@86 93 each iteration. */
cannam@86 94
cannam@86 95 for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
cannam@86 96 r/=error;
cannam@86 97
cannam@86 98 /* Update LPC coefficients and total error */
cannam@86 99
cannam@86 100 lpc[i]=r;
cannam@86 101 for(j=0;j<i/2;j++){
cannam@86 102 double tmp=lpc[j];
cannam@86 103
cannam@86 104 lpc[j]+=r*lpc[i-1-j];
cannam@86 105 lpc[i-1-j]+=r*tmp;
cannam@86 106 }
cannam@86 107 if(i&1)lpc[j]+=lpc[j]*r;
cannam@86 108
cannam@86 109 error*=1.-r*r;
cannam@86 110
cannam@86 111 }
cannam@86 112
cannam@86 113 done:
cannam@86 114
cannam@86 115 /* slightly damp the filter */
cannam@86 116 {
cannam@86 117 double g = .99;
cannam@86 118 double damp = g;
cannam@86 119 for(j=0;j<m;j++){
cannam@86 120 lpc[j]*=damp;
cannam@86 121 damp*=g;
cannam@86 122 }
cannam@86 123 }
cannam@86 124
cannam@86 125 for(j=0;j<m;j++)lpci[j]=(float)lpc[j];
cannam@86 126
cannam@86 127 /* we need the error value to know how big an impulse to hit the
cannam@86 128 filter with later */
cannam@86 129
cannam@86 130 return error;
cannam@86 131 }
cannam@86 132
cannam@86 133 void vorbis_lpc_predict(float *coeff,float *prime,int m,
cannam@86 134 float *data,long n){
cannam@86 135
cannam@86 136 /* in: coeff[0...m-1] LPC coefficients
cannam@86 137 prime[0...m-1] initial values (allocated size of n+m-1)
cannam@86 138 out: data[0...n-1] data samples */
cannam@86 139
cannam@86 140 long i,j,o,p;
cannam@86 141 float y;
cannam@86 142 float *work=alloca(sizeof(*work)*(m+n));
cannam@86 143
cannam@86 144 if(!prime)
cannam@86 145 for(i=0;i<m;i++)
cannam@86 146 work[i]=0.f;
cannam@86 147 else
cannam@86 148 for(i=0;i<m;i++)
cannam@86 149 work[i]=prime[i];
cannam@86 150
cannam@86 151 for(i=0;i<n;i++){
cannam@86 152 y=0;
cannam@86 153 o=i;
cannam@86 154 p=m;
cannam@86 155 for(j=0;j<m;j++)
cannam@86 156 y-=work[o++]*coeff[--p];
cannam@86 157
cannam@86 158 data[i]=work[o]=y;
cannam@86 159 }
cannam@86 160 }