tap_utils.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /* -*- linux-c -*-
  2. Copyright (C) 2004 Tom Szilagyi
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. $Id: tap_utils.h,v 1.5 2004/02/21 17:33:36 tszilagyi Exp $
  15. */
  16. #ifndef _ISOC99_SOURCE
  17. #define _ISOC99_SOURCE
  18. #endif
  19. #include <stdint.h>
  20. #ifndef M_PI
  21. #define M_PI 3.14159265358979323846264338327
  22. #endif
  23. /* push a sample into a ringbuffer and return the sample falling out */
  24. static inline
  25. LADSPA_Data
  26. push_buffer(LADSPA_Data insample, LADSPA_Data * buffer,
  27. unsigned long buflen, unsigned long * pos) {
  28. LADSPA_Data outsample;
  29. outsample = buffer[*pos];
  30. buffer[(*pos)++] = insample;
  31. if (*pos >= buflen)
  32. *pos = 0;
  33. return outsample;
  34. }
  35. /* read a value from a ringbuffer.
  36. * n == 0 returns the oldest sample from the buffer.
  37. * n == buflen-1 returns the sample written to the buffer
  38. * at the last push_buffer call.
  39. * n must not exceed buflen-1, or your computer will explode.
  40. */
  41. static inline
  42. LADSPA_Data
  43. read_buffer(LADSPA_Data * buffer, unsigned long buflen,
  44. unsigned long pos, unsigned long n) {
  45. while (n + pos >= buflen)
  46. n -= buflen;
  47. return buffer[n + pos];
  48. }
  49. /* overwrites a value in a ringbuffer, but pos stays the same.
  50. * n == 0 overwrites the oldest sample pushed in the buffer.
  51. * n == buflen-1 overwrites the sample written to the buffer
  52. * at the last push_buffer call.
  53. * n must not exceed buflen-1, or your computer... you know.
  54. */
  55. static inline
  56. void
  57. write_buffer(LADSPA_Data insample, LADSPA_Data * buffer, unsigned long buflen,
  58. unsigned long pos, unsigned long n) {
  59. while (n + pos >= buflen)
  60. n -= buflen;
  61. buffer[n + pos] = insample;
  62. }
  63. /* Please note that the majority of the definitions and helper
  64. functions below have been derived from the source code of Steve
  65. Harris's SWH plugins (particularly from the "biquad.h" file). While I
  66. give him credit for his excellent work, I reserve myself to be blamed
  67. for any bugs or malfunction. */
  68. #define db2lin(x) ((x) > -90.0f ? powf(10.0f, (x) * 0.05f) : 0.0f)
  69. #define ABS(x) (x)>0.0f?(x):-1.0f*(x)
  70. #define LN_2_2 0.34657359f
  71. #define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v)))
  72. #define BIQUAD_TYPE float
  73. typedef BIQUAD_TYPE bq_t;
  74. /* Biquad filter (adapted from lisp code by Eli Brandt,
  75. http://www.cs.cmu.edu/~eli/) */
  76. /* The prev. comment has been preserved from Steve Harris's biquad.h */
  77. typedef struct {
  78. bq_t a1;
  79. bq_t a2;
  80. bq_t b0;
  81. bq_t b1;
  82. bq_t b2;
  83. bq_t x1;
  84. bq_t x2;
  85. bq_t y1;
  86. bq_t y2;
  87. } biquad;
  88. static inline void biquad_init(biquad *f) {
  89. f->x1 = 0.0f;
  90. f->x2 = 0.0f;
  91. f->y1 = 0.0f;
  92. f->y2 = 0.0f;
  93. }
  94. static inline
  95. void
  96. eq_set_params(biquad *f, bq_t fc, bq_t gain, bq_t bw, bq_t fs) {
  97. bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0f, fs/2.0f) / fs;
  98. bq_t cw = cosf(w);
  99. bq_t sw = sinf(w);
  100. bq_t J = pow(10.0f, gain * 0.025f);
  101. bq_t g = sw * sinhf(LN_2_2 * LIMIT(bw, 0.0001f, 4.0f) * w / sw);
  102. bq_t a0r = 1.0f / (1.0f + (g / J));
  103. f->b0 = (1.0f + (g * J)) * a0r;
  104. f->b1 = (-2.0f * cw) * a0r;
  105. f->b2 = (1.0f - (g * J)) * a0r;
  106. f->a1 = -(f->b1);
  107. f->a2 = ((g / J) - 1.0f) * a0r;
  108. }
  109. static inline void lp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs) {
  110. bq_t omega = 2.0 * M_PI * fc/fs;
  111. bq_t sn = sin(omega);
  112. bq_t cs = cos(omega);
  113. bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
  114. const float a0r = 1.0 / (1.0 + alpha);
  115. #if 0
  116. b0 = (1 - cs) /2;
  117. b1 = 1 - cs;
  118. b2 = (1 - cs) /2;
  119. a0 = 1 + alpha;
  120. a1 = -2 * cs;
  121. a2 = 1 - alpha;
  122. #endif
  123. f->b0 = a0r * (1.0 - cs) * 0.5;
  124. f->b1 = a0r * (1.0 - cs);
  125. f->b2 = a0r * (1.0 - cs) * 0.5;
  126. f->a1 = a0r * (2.0 * cs);
  127. f->a2 = a0r * (alpha - 1.0);
  128. }
  129. static inline
  130. void
  131. hp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs)
  132. {
  133. bq_t omega = 2.0 * M_PI * fc/fs;
  134. bq_t sn = sin(omega);
  135. bq_t cs = cos(omega);
  136. bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
  137. const float a0r = 1.0 / (1.0 + alpha);
  138. #if 0
  139. b0 = (1 + cs) /2;
  140. b1 = -(1 + cs);
  141. b2 = (1 + cs) /2;
  142. a0 = 1 + alpha;
  143. a1 = -2 * cs;
  144. a2 = 1 - alpha;
  145. #endif
  146. f->b0 = a0r * (1.0 + cs) * 0.5;
  147. f->b1 = a0r * -(1.0 + cs);
  148. f->b2 = a0r * (1.0 + cs) * 0.5;
  149. f->a1 = a0r * (2.0 * cs);
  150. f->a2 = a0r * (alpha - 1.0);
  151. }
  152. static inline
  153. void
  154. ls_set_params(biquad *f, bq_t fc, bq_t gain, bq_t slope, bq_t fs)
  155. {
  156. bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0, fs/2.0) / fs;
  157. bq_t cw = cosf(w);
  158. bq_t sw = sinf(w);
  159. bq_t A = powf(10.0f, gain * 0.025f);
  160. bq_t b = sqrt(((1.0f + A * A) / LIMIT(slope, 0.0001f, 1.0f)) - ((A -
  161. 1.0f) * (A - 1.0)));
  162. bq_t apc = cw * (A + 1.0f);
  163. bq_t amc = cw * (A - 1.0f);
  164. bq_t bs = b * sw;
  165. bq_t a0r = 1.0f / (A + 1.0f + amc + bs);
  166. f->b0 = a0r * A * (A + 1.0f - amc + bs);
  167. f->b1 = a0r * 2.0f * A * (A - 1.0f - apc);
  168. f->b2 = a0r * A * (A + 1.0f - amc - bs);
  169. f->a1 = a0r * 2.0f * (A - 1.0f + apc);
  170. f->a2 = a0r * (-A - 1.0f - amc + bs);
  171. }
  172. static inline
  173. void
  174. hs_set_params(biquad *f, bq_t fc, bq_t gain, bq_t slope, bq_t fs) {
  175. bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0, fs/2.0) / fs;
  176. bq_t cw = cosf(w);
  177. bq_t sw = sinf(w);
  178. bq_t A = powf(10.0f, gain * 0.025f);
  179. bq_t b = sqrt(((1.0f + A * A) / LIMIT(slope, 0.0001f, 1.0f)) - ((A -
  180. 1.0f) * (A - 1.0f)));
  181. bq_t apc = cw * (A + 1.0f);
  182. bq_t amc = cw * (A - 1.0f);
  183. bq_t bs = b * sw;
  184. bq_t a0r = 1.0f / (A + 1.0f - amc + bs);
  185. f->b0 = a0r * A * (A + 1.0f + amc + bs);
  186. f->b1 = a0r * -2.0f * A * (A - 1.0f + apc);
  187. f->b2 = a0r * A * (A + 1.0f + amc - bs);
  188. f->a1 = a0r * -2.0f * (A - 1.0f - apc);
  189. f->a2 = a0r * (-A - 1.0f + amc + bs);
  190. }
  191. static inline
  192. bq_t
  193. biquad_run(biquad *f, bq_t x) {
  194. union {
  195. bq_t y;
  196. uint32_t y_int;
  197. } u;
  198. u.y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
  199. + f->a1 * f->y1 + f->a2 * f->y2;
  200. if ((u.y_int & 0x7f800000) == 0)
  201. u.y = 0.0f;
  202. f->x2 = f->x1;
  203. f->x1 = x;
  204. f->y2 = f->y1;
  205. f->y1 = u.y;
  206. return u.y;
  207. }