filter.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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. implements fir antialiasing filter : should help when setting sample
  17. rates as low as 8Khz.
  18. April 95
  19. - first draft
  20. 22/5/95
  21. - modify "filter" so that it simulate leading and trailing 0 in the buffer
  22. */
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <math.h>
  26. #include <stdlib.h>
  27. #include "config.h"
  28. #include "common.h"
  29. #include "controls.h"
  30. #include "instrum.h"
  31. #include "filter.h"
  32. void Real_Tim_Free( void *pt );
  33. /* bessel function */
  34. static float ino(float x)
  35. {
  36. float y, de, e, sde;
  37. int i;
  38. y = x / 2;
  39. e = 1.0;
  40. de = 1.0;
  41. i = 1;
  42. do {
  43. de = de * y / (float) i;
  44. sde = de * de;
  45. e += sde;
  46. } while (!( (e * 1.0e-08 - sde > 0) || (i++ > 25) ));
  47. return(e);
  48. }
  49. /* Kaiser Window (symetric) */
  50. static void kaiser(float *w,int n,float beta)
  51. {
  52. float xind, xi;
  53. int i;
  54. xind = (float)((2*n - 1) * (2*n - 1));
  55. for (i =0; i<n ; i++)
  56. {
  57. xi = (float)(i + 0.5);
  58. w[i] = ino((float)(beta * sqrt((double)(1. - 4 * xi * xi / xind))))
  59. / ino((float)beta);
  60. }
  61. }
  62. /*
  63. * fir coef in g, cuttoff frequency in fc
  64. */
  65. static void designfir(float *g , float fc)
  66. {
  67. int i;
  68. float xi, omega, att, beta ;
  69. float w[ORDER2];
  70. for (i =0; i < ORDER2 ;i++)
  71. {
  72. xi = (float) (i + 0.5);
  73. omega = (float)(PI * xi);
  74. g[i] = (float)(sin( (double) omega * fc) / omega);
  75. }
  76. att = 40.; /* attenuation in db */
  77. beta = (float) (exp(log((double)0.58417 * (att - 20.96)) * 0.4) + 0.07886
  78. * (att - 20.96));
  79. kaiser( w, ORDER2, beta);
  80. /* Matrix product */
  81. for (i =0; i < ORDER2 ; i++)
  82. g[i] = g[i] * w[i];
  83. }
  84. /*
  85. * FIR filtering -> apply the filter given by coef[] to the data buffer
  86. * Note that we simulate leading and trailing 0 at the border of the
  87. * data buffer
  88. */
  89. static void filter(sample_t *result,sample_t *data, int32_t length,float coef[])
  90. {
  91. int32_t sample,i,sample_window;
  92. int16_t peak = 0;
  93. float sum;
  94. /* Simulate leading 0 at the begining of the buffer */
  95. for (sample = 0; sample < ORDER2 ; sample++ )
  96. {
  97. sum = 0.0;
  98. sample_window= sample - ORDER2;
  99. for (i = 0; i < ORDER ;i++)
  100. sum += (float)(coef[i] *
  101. ((sample_window<0)? 0.0 : data[sample_window++])) ;
  102. /* Saturation ??? */
  103. if (sum> 32767.) { sum=32767.; peak++; }
  104. if (sum< -32768.) { sum=-32768; peak++; }
  105. result[sample] = (sample_t) sum;
  106. }
  107. /* The core of the buffer */
  108. for (sample = ORDER2; sample < length - ORDER + ORDER2 ; sample++ )
  109. {
  110. sum = 0.0;
  111. sample_window= sample - ORDER2;
  112. for (i = 0; i < ORDER ;i++)
  113. sum += data[sample_window++] * coef[i];
  114. /* Saturation ??? */
  115. if (sum> 32767.) { sum=32767.; peak++; }
  116. if (sum< -32768.) { sum=-32768; peak++; }
  117. result[sample] = (sample_t) sum;
  118. }
  119. /* Simulate 0 at the end of the buffer */
  120. for (sample = length - ORDER + ORDER2; sample < length ; sample++ )
  121. {
  122. sum = 0.0;
  123. sample_window= sample - ORDER2;
  124. for (i = 0; i < ORDER ;i++)
  125. sum += (float)(coef[i] *
  126. ((sample_window>=length)? 0.0 : data[sample_window++])) ;
  127. /* Saturation ??? */
  128. if (sum> 32767.) { sum=32767.; peak++; }
  129. if (sum< -32768.) { sum=-32768; peak++; }
  130. result[sample] = (sample_t) sum;
  131. }
  132. if (peak)
  133. ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
  134. "Saturation %2.3f %%.", 100.0*peak/ (float) length);
  135. }
  136. /***********************************************************************/
  137. /* Prevent aliasing by filtering any freq above the output_rate */
  138. /* */
  139. /* I don't worry about looping point -> they will remain soft if they */
  140. /* were already */
  141. /***********************************************************************/
  142. void antialiasing(Sample *sp, int32_t output_rate )
  143. {
  144. sample_t *temp;
  145. int i;
  146. float fir_symetric[ORDER];
  147. float fir_coef[ORDER2];
  148. float freq_cut; /* cutoff frequency [0..1.0] FREQ_CUT/SAMP_FREQ*/
  149. ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: Fsample=%iKHz",
  150. sp->sample_rate);
  151. /* No oversampling */
  152. if (output_rate>=sp->sample_rate)
  153. return;
  154. freq_cut= (float) output_rate / (float) sp->sample_rate;
  155. ctl->cmsg(CMSG_INFO, VERB_NOISY, "Antialiasing: cutoff=%f%%",
  156. freq_cut*100.);
  157. designfir(fir_coef,freq_cut);
  158. /* Make the filter symetric */
  159. for (i = 0 ; i<ORDER2 ;i++)
  160. fir_symetric[ORDER-1 - i] = fir_symetric[i] = fir_coef[ORDER2-1 - i];
  161. /* We apply the filter we have designed on a copy of the patch */
  162. temp = (sample_t*)safe_malloc(sp->data_length);
  163. memcpy(temp,sp->data,sp->data_length);
  164. filter(sp->data,temp,sp->data_length/sizeof(sample_t),fir_symetric);
  165. Real_Tim_Free(temp);
  166. }