TwelveAX7.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. dsp/TwelveAX7.h
  3. Copyright 2003-6 Tim Goetze <tim@quitte.de>
  4. http://quitte.de/dsp/
  5. collection of approximations of the 12AX7 voltage transfer function
  6. */
  7. /*
  8. This program is free software; you can redistribute it and/or
  9. modify it under the terms of the GNU General Public License
  10. as published by the Free Software Foundation; either version 2
  11. of the License, or (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19. 02111-1307, USA or point your web browser to http://www.gnu.org.
  20. */
  21. #ifndef _DSP_TWELVE_AX_7_H_
  22. #define _DSP_TWELVE_AX_7_H_
  23. namespace DSP {
  24. #include "r12ax7.h"
  25. typedef sample_t tube_sample;
  26. /* this is the original tube model from caps < 0.1.9 or preamp.so, put
  27. * back into use in 0.1.11; the replacement (below) is too strong in
  28. * odd-order harmonics at the expense of even-order. it has to sound
  29. * good: it took a good deal of fiddling to get the coefficients right.
  30. */
  31. class TwelveAX7
  32. {
  33. public:
  34. tube_sample b, c, d;
  35. struct {
  36. tube_sample threshold, value;
  37. } clip[2];
  38. /* amplitude at which clipping starts */
  39. tube_sample scale;
  40. public:
  41. TwelveAX7()
  42. {
  43. /* transfer polynomial parameters */
  44. b = -0.79618574210627535;
  45. c = -0.21108555430962023;
  46. d = +0.38944033523200522;
  47. set_clips();
  48. scale = min (fabs (clip[0].threshold), fabs (clip[1].threshold));
  49. }
  50. inline tube_sample transfer (tube_sample a)
  51. {
  52. return a * (b + a * (c + a * d));
  53. }
  54. inline tube_sample transfer_clip (tube_sample a)
  55. {
  56. if (a <= clip[0].threshold)
  57. return clip[0].value;
  58. if (a >= clip[1].threshold)
  59. return clip[1].value;
  60. return transfer (a);
  61. }
  62. inline double get_root (double sign)
  63. {
  64. /* only once, no need to optimize */
  65. return
  66. (-2*c + sign * sqrt ((2*c) * (2*c) - 4 * (3 * d * b))) / (6 * d);
  67. }
  68. inline void set_clips()
  69. {
  70. /* find 0 crossings in the derived, this is where we'll clip */
  71. double x0 = get_root (-1);
  72. double x1 = get_root (+1);
  73. clip[0].value = transfer (x0);
  74. clip[1].value = transfer (x1);
  75. clip[0].threshold = x0;
  76. clip[1].threshold = x1;
  77. }
  78. };
  79. /* reworked model. higher order (than 3) polynomials make little sense;
  80. * sonically the difference is minim, and the cycle count increases
  81. * dramatically.
  82. */
  83. class TwelveAX7_2
  84. {
  85. public:
  86. tube_sample b, c, d;
  87. struct {
  88. tube_sample threshold, value;
  89. } clip[2];
  90. tube_sample scale;
  91. public:
  92. TwelveAX7_2()
  93. {
  94. /* transfer polynomial parameters, made with gnuplot::fit() */
  95. b = -1.08150605597883;
  96. c = -0.262760944760536;
  97. d = 0.445770802765903;
  98. static double x[2] = {-.52, +.98};
  99. for (int i = 0; i < 2; ++i)
  100. clip[i].threshold = x[i],
  101. clip[i].value = transfer (x[i]);
  102. scale = min (fabs (clip[0].threshold), fabs (clip[1].threshold));
  103. }
  104. inline tube_sample transfer (tube_sample a)
  105. {
  106. return a * (b + a * (c + a * d));
  107. }
  108. inline tube_sample transfer_clip (tube_sample a)
  109. {
  110. if (a <= clip[0].threshold)
  111. return clip[0].value;
  112. if (a >= clip[1].threshold)
  113. return clip[1].value;
  114. return transfer (a);
  115. }
  116. };
  117. /* third model relies on linear interpolation based on the transfer function
  118. * as calculated from a spice model.
  119. */
  120. class TwelveAX7_3
  121. {
  122. public:
  123. tube_sample b, c, d;
  124. struct {
  125. tube_sample threshold, value;
  126. } clip[2];
  127. tube_sample scale;
  128. public:
  129. TwelveAX7_3()
  130. {
  131. static double x[2] =
  132. {
  133. (double) r12AX7::Zero /
  134. ((double) r12AX7::Samples - (double) r12AX7::Zero),
  135. 1
  136. };
  137. for (int i = 0; i < 2; ++i)
  138. clip[i].threshold = x[i],
  139. clip[i].value = transfer (x[i]);
  140. scale = min (fabs (clip[0].threshold), fabs (clip[1].threshold));
  141. }
  142. inline tube_sample transfer (tube_sample a)
  143. {
  144. a = r12AX7::Zero + a * (r12AX7::Samples - r12AX7::Zero);
  145. if (a <= 0)
  146. return r12AX7::v2v[0];
  147. if (a >= r12AX7::Samples - 1)
  148. return r12AX7::v2v [r12AX7::Samples - 1];
  149. /* linear interpolation from sampled function */
  150. register int i = lrintf (a);
  151. a -= i;
  152. return (r12AX7::v2v [i] * (1.f - a) + r12AX7::v2v [i + 1] * a);
  153. }
  154. inline tube_sample transfer_clip (tube_sample a)
  155. {
  156. return transfer (a);
  157. }
  158. };
  159. /* experimental */
  160. class NoTwelveAX7
  161. {
  162. public:
  163. struct {
  164. tube_sample threshold, value;
  165. } clip[2];
  166. /* amplitude at which clipping starts */
  167. tube_sample scale;
  168. public:
  169. NoTwelveAX7()
  170. {
  171. static double x[2] = { -1, 1 };
  172. for (int i = 0; i < 2; ++i)
  173. clip[i].threshold = x[i],
  174. clip[i].value = transfer (x[i]);
  175. scale = min (fabs (clip[0].threshold), fabs (clip[1].threshold));
  176. }
  177. inline tube_sample transfer (tube_sample a)
  178. {
  179. return 0.5469181606780 * (pow (1 - a, 1.5) - 1);
  180. }
  181. inline tube_sample transfer_clip (tube_sample a)
  182. {
  183. if (a <= clip[0].threshold)
  184. return clip[0].value;
  185. if (a >= clip[1].threshold)
  186. return clip[1].value;
  187. return transfer (a);
  188. }
  189. };
  190. } /* namespace DSP */
  191. #endif /* _DSP_TWELVE_AX_7_H_ */