blob: ba0e4655442d271470815a7bd7b87b061c083044 [file] [log] [blame]
/* Copyright (C) 2002 Jean-Marc Valin
File: filters.c
Various analysis/synthesis filters
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "filters.h"
#include <stdio.h>
#define min(a,b) ((a) < (b) ? (a) : (b))
void print_vec(float *vec, int len, char *name)
{
int i;
printf ("%s ", name);
for (i=0;i<len;i++)
printf (" %f", vec[i]);
printf ("\n");
}
void bw_lpc(float gamma, float *lpc_in, float *lpc_out, int order)
{
int i;
float tmp=1;
for (i=0;i<order+1;i++)
{
lpc_out[i] = tmp * lpc_in[i];
tmp *= gamma;
}
}
void syn_filt(float *x, float *a, float *y, int N, int ord)
{
int i,j;
for (i=0;i<N;i++)
{
y[i]=x[i];
for (j=1;j<=ord;j++)
y[i] -= a[j]*y[i-j];
}
}
void syn_filt_zero(float *x, float *a, float *y, int N, int ord)
{
int i,j;
for (i=0;i<N;i++)
{
y[i]=x[i];
for (j=1;j<=min(ord,i);j++)
y[i] -= a[j]*y[i-j];
}
}
void syn_filt_mem(float *x, float *a, float *y, int N, int ord, float *mem)
{
int i,j;
for (i=0;i<N;i++)
{
y[i]=x[i];
for (j=1;j<=min(ord,i);j++)
y[i] -= a[j]*y[i-j];
for (j=i+1;j<=ord;j++)
y[i] -= a[j]*mem[j-i-1];
}
for (i=0;i<ord;i++)
mem[i]=y[N-i-1];
}
void residue(float *x, float *a, float *y, int N, int ord)
{
int i,j;
for (i=N-1;i>=0;i--)
{
y[i]=x[i];
for (j=1;j<=ord;j++)
y[i] += a[j]*x[i-j];
}
}
void residue_zero(float *x, float *a, float *y, int N, int ord)
{
int i,j;
for (i=N-1;i>=0;i--)
{
y[i]=x[i];
for (j=1;j<=min(ord,i);j++)
y[i] += a[j]*x[i-j];
}
}
void residue_mem(float *x, float *a, float *y, int N, int ord, float *mem)
{
int i,j;
for (i=N-1;i>=0;i--)
{
y[i]=x[i];
for (j=1;j<=min(ord,i);j++)
y[i] += a[j]*x[i-j];
for (j=i+1;j<=ord;j++)
y[i] += a[j]*mem[j-i-1];
}
for (i=0;i<ord;i++)
mem[i]=x[N-i-1];
}
float xcorr(float *x, float *y, int len)
{
int i;
float sum=0;
for (i=0;i<len;i++)
sum += x[i]*y[i];
return sum;
}
/*
void fir_mem(float *x, float *a, float *y, int N, int M, float *mem)
{
int i,j;
for (i=0;i<N;i++)
{
y[i]=0;
for (j=0;j<=min(M-1,i);j++)
y[i] += a[j]*x[i-j];
for (j=i+1;j<=M-1;j++)
y[i] += a[j]*mem[j-i-1];
}
for (i=0;i<M-1;i++)
mem[i]=x[N-i-1];
}
*/
void syn_percep_zero(float *xx, float *ak, float *awk1, float *awk2, float *y, int N, int ord)
{
int i,j;
float long_filt[21];
float iir[20];
float fir[10];
float x[40];
int ord2=ord<<1;
for (i=0;i<=ord;i++)
long_filt[i]=ak[i];
for (i=ord+1;i<=ord2;i++)
long_filt[i]=0;
residue_zero(long_filt,awk2,long_filt,1+(ord<<1),ord);
for (i=0;i<N;i++)
x[i]=xx[i];
for (i=0;i<ord2;i++)
iir[i]=long_filt[ord2-i];
for (i=0;i<ord;i++)
fir[i]=awk1[ord-i];
for (i=0;i<ord2;i++)
{
y[i]=x[i];
for (j=1;j<=min(ord2,i);j++)
y[i] -= long_filt[j]*y[i-j];
for (j=1;j<=min(ord,i);j++)
y[i] += awk1[j]*x[i-j];
}
#if 0
for (i=ord2;i<N;i++)
{
float *yptr=y+i-ord2;
float *xptr=x+i-ord;
y[i]=x[i];
for (j=0;j<ord2;j++)
y[i]-= iir[j]*yptr[j];
for (j=0;j<ord;j++)
y[i]+= fir[j]*xptr[j];
}
#else
for (i=ord2;i<N;i++)
{
float *f, *ptr;
float sum1=x[i], sum2=0;
f=iir;
ptr=y+i-ord2;
for (j=0;j<ord2;j+=2)
{
sum1-= f[0]*ptr[0];
sum2-= f[1]*ptr[1];
f+=2;
ptr+=2;
}
f=fir;
ptr=x+i-ord;
for (j=0;j<ord;j+=2)
{
sum1+= f[0]*ptr[0];
sum2+= f[1]*ptr[1];
f+=2;
ptr+=2;
}
y[i]=sum1+sum2;
}
#endif
}
#define MAX_FILTER 100
#define MAX_SIGNAL 1000
void fir_mem(float *xx, float *aa, float *y, int N, int M, float *mem)
{
int i,j;
float a[MAX_FILTER];
float x[MAX_SIGNAL];
for (i=0;i<M;i++)
a[M-i-1]=aa[i];
for (i=0;i<M-1;i++)
x[i]=mem[M-i-2];
for (i=0;i<N;i++)
x[i+M-1]=xx[i];
for (i=0;i<N;i++)
{
y[i]=0;
for (j=0;j<M;j++)
y[i]+=a[j]*x[i+j];
}
for (i=0;i<M-1;i++)
mem[i]=xx[N-i-1];
}