filter.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:6k
源码类别:

多媒体编程

开发平台:

DOS

  1. /*
  2.     TiMidity -- Experimental MIDI to WAVE converter
  3.     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.     GNU General Public License for more details.
  12.     You should have received a copy of the GNU General Public License
  13.     along with this program; if not, write to the Free Software
  14.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.    filter.c: written by Vincent Pagel ( pagel@loria.fr ) 
  16.  
  17.    implements fir antialiasing filter : should help when setting sample
  18.    rates as low as 8Khz.
  19.    April 95
  20.       - first draft
  21.    22/5/95
  22.       - modify "filter" so that it simulate leading and trailing 0 in the buffer
  23.    */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <math.h>
  27. #include <stdlib.h>
  28. #include "config.h"
  29. #include "common.h"
  30. #include "ctrlmode.h"
  31. #include "instrum.h"
  32. #include "filter.h"
  33. /*  bessel  function   */
  34. static float ino(float x)
  35. {
  36.     float y, de, e, sde;
  37.     int i;
  38.     
  39.     y = x / 2;
  40.     e = 1.0;
  41.     de = 1.0;
  42.     i = 1;
  43.     do {
  44. de = de * y / (float) i;
  45. sde = de * de;
  46. e += sde;
  47.     } while (!( (e * 1.0e-08 - sde > 0) || (i++ > 25) ));
  48.     return(e);
  49. }
  50. /* Kaiser Window (symetric) */
  51. static void kaiser(float *w,int n,float beta)
  52. {
  53.     float xind, xi;
  54.     int i;
  55.     
  56.     xind = (float)((2*n - 1) * (2*n - 1));
  57.     for (i =0; i<n ; i++) 
  58. {
  59.     xi = (float)(i + 0.5);
  60.     w[i] = ino((float)(beta * sqrt((double)(1. - 4 * xi * xi / xind))))
  61. / ino((float)beta);
  62. }
  63. }
  64. /*
  65.  * fir coef in g, cuttoff frequency in fc
  66.  */
  67. static void designfir(float *g , float fc)
  68. {
  69.     int i;
  70.     float xi, omega, att, beta ;
  71.     float w[ORDER2];
  72.     
  73.     for (i =0; i < ORDER2 ;i++) 
  74. {
  75.     xi = (float) (i + 0.5);
  76.     omega = (float)(PI * xi);
  77.     g[i] = (float)(sin( (double) omega * fc) / omega);
  78. }
  79.     
  80.     att = 40.; /* attenuation  in  db */
  81.     beta = (float) (exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886 
  82. * (att - 20.96));
  83.     kaiser( w, ORDER2, beta);
  84.     
  85.     /* Matrix product */
  86.     for (i =0; i < ORDER2 ; i++)
  87. g[i] = g[i] * w[i];
  88. }
  89. /*
  90.  * FIR filtering -> apply the filter given by coef[] to the data buffer
  91.  * Note that we simulate leading and trailing 0 at the border of the 
  92.  * data buffer
  93.  */
  94. static void filter(sample_t *result,sample_t *data, int32 length,float coef[])
  95. {
  96.     int32 sample,i,sample_window;
  97.     int16 peak = 0;
  98.     float sum;
  99.     /* Simulate leading 0 at the begining of the buffer */
  100.      for (sample = 0; sample < ORDER2 ; sample++ )
  101. {
  102.     sum = 0.0;
  103.     sample_window= sample - ORDER2;
  104.    
  105.     for (i = 0; i < ORDER ;i++) 
  106. sum += (float)(coef[i] *
  107.     ((sample_window<0)? 0.0 : data[sample_window++])) ;
  108.     
  109.     /* Saturation ??? */
  110.     if (sum> 32767.) { sum=32767.; peak++; }
  111.     if (sum< -32768.) { sum=-32768; peak++; }
  112.     result[sample] = (sample_t) sum;
  113. }
  114.     /* The core of the buffer  */
  115.     for (sample = ORDER2; sample < length - ORDER + ORDER2 ; sample++ )
  116. {
  117.     sum = 0.0;
  118.     sample_window= sample - ORDER2;
  119.     for (i = 0; i < ORDER ;i++) 
  120. sum += data[sample_window++] * coef[i];
  121.     
  122.     /* Saturation ??? */
  123.     if (sum> 32767.) { sum=32767.; peak++; }
  124.     if (sum< -32768.) { sum=-32768; peak++; }
  125.     result[sample] = (sample_t) sum;
  126. }
  127.     
  128.     /* Simulate 0 at the end of the buffer */
  129.     for (sample = length - ORDER + ORDER2; sample < length ; sample++ )
  130. {
  131.     sum = 0.0;
  132.     sample_window= sample - ORDER2;
  133.     
  134.     for (i = 0; i < ORDER ;i++) 
  135. sum += (float)(coef[i] *
  136.     ((sample_window>=length)? 0.0 : data[sample_window++])) ;
  137.     
  138.     /* Saturation ??? */
  139.     if (sum> 32767.) { sum=32767.; peak++; }
  140.     if (sum< -32768.) { sum=-32768; peak++; }
  141.     result[sample] = (sample_t) sum;
  142. }
  143.     if (peak)
  144. ctl->cmsg(CMSG_ERROR, VERB_NORMAL, 
  145.   "Saturation %2.3f %%.", 100.0*peak/ (float) length);
  146. }
  147. /***********************************************************************/
  148. /* Prevent aliasing by filtering any freq above the output_rate        */
  149. /*                                                                     */
  150. /* I don't worry about looping point -> they will remain soft if they  */
  151. /* were already                                                        */
  152. /***********************************************************************/
  153. void antialiasing(Sample *sp, int32 output_rate )
  154. {
  155.     sample_t *temp;
  156.     int i;
  157.     float fir_symetric[ORDER];
  158.     float fir_coef[ORDER2];
  159.     float freq_cut;  /* cutoff frequency [0..1.0] FREQ_CUT/SAMP_FREQ*/
  160.  
  161.     ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: Fsample=%iKHz",
  162.       sp->sample_rate);
  163.  
  164.     /* No oversampling  */
  165.     if (output_rate>=sp->sample_rate)
  166. return;
  167.     
  168.     freq_cut= (float) output_rate / (float) sp->sample_rate;
  169.     ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: cutoff=%f%%",
  170.       freq_cut*100.);
  171.     designfir(fir_coef,freq_cut);
  172.     
  173.     /* Make the filter symetric */
  174.     for (i = 0 ; i<ORDER2 ;i++) 
  175. fir_symetric[ORDER-1 - i] = fir_symetric[i] = fir_coef[ORDER2-1 - i];
  176.     
  177.     /* We apply the filter we have designed on a copy of the patch */
  178.     temp = safe_malloc(sp->data_length);
  179.     memcpy(temp,sp->data,sp->data_length);
  180.     
  181.     filter(sp->data,temp,sp->data_length/sizeof(sample_t),fir_symetric);
  182.     
  183.     free(temp);
  184. }