Amp.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /*
  2. Amp.cc
  3. Copyright 2003-7
  4. Tim Goetze <tim@quitte.de>
  5. David Yeh <dtyeh@ccrma.stanford.edu> (Tone Stack in TS models)
  6. http://quitte.de/dsp/
  7. Tube amplifier models
  8. */
  9. /*
  10. This program is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU General Public License
  12. as published by the Free Software Foundation; either version 2
  13. of the License, or (at your option) any later version.
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. GNU General Public License for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with this program; if not, write to the Free Software
  20. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  21. 02111-1307, USA or point your web browser to http://www.gnu.org.
  22. */
  23. #include "basics.h"
  24. #include <stdio.h>
  25. #include "Amp.h"
  26. #include "Descriptor.h"
  27. void
  28. AmpStub::init (bool adjust_downsampler)
  29. {
  30. dc_blocker.set_f (10. / fs);
  31. /* going a bit lower than nominal with fc */
  32. double f = .7 * M_PI / OVERSAMPLE;
  33. /* construct the upsampler filter kernel */
  34. DSP::sinc (f, up.c, FIR_SIZE);
  35. DSP::kaiser<DSP::apply_window> (up.c, FIR_SIZE, 6.4);
  36. /* copy upsampler filter kernel for downsampler, make sum */
  37. double s = 0;
  38. for (int i = 0; i < up.n; ++i)
  39. down.c[i] = up.c[i],
  40. s += up.c[i];
  41. s = 1 / s;
  42. /* scale downsampler kernel for unity gain + correction for transfer */
  43. double t = adjust_downsampler ?
  44. s / max (fabs (tube.clip[0].value), fabs (tube.clip[1].value)) : s;
  45. for (int i = 0; i < down.n; ++i)
  46. down.c[i] *= t;
  47. /* scale upsampler kernel for unity gain */
  48. s *= OVERSAMPLE;
  49. for (int i = 0; i < up.n; ++i)
  50. up.c[i] *= s;
  51. }
  52. /* //////////////////////////////////////////////////////////////////////// */
  53. void
  54. AmpIII::init()
  55. {
  56. this->AmpStub::init (false);
  57. /* need to filter out dc before the power amp stage, which is running at
  58. * the oversampled rate */
  59. dc_blocker.set_f (10. / (fs * OVERSAMPLE));
  60. DSP::RBJ::LoShelve (200 / fs, .2, -3, filter.a, filter.b);
  61. }
  62. template <sample_func_t F, int OVERSAMPLE>
  63. void
  64. AmpIII::one_cycle (int frames)
  65. {
  66. sample_t * s = ports[0];
  67. sample_t gain = getport(1);
  68. sample_t temp = getport(2) * tube.scale;
  69. drive = getport(3) * .5;
  70. i_drive = 1 / (1 - drive);
  71. sample_t * d = ports[4];
  72. *ports[5] = OVERSAMPLE;
  73. double g = current.g;
  74. current.g = max (gain < 1 ? gain : exp2 (gain - 1), .000001);
  75. current.g *= tube.scale / fabs (tube.transfer (temp));
  76. /* recursive fade to prevent zipper noise from the 'gain' knob */
  77. if (g == 0) g = current.g;
  78. double one_over_n = frames > 0 ? 1. / frames : 1;
  79. double gf = pow (current.g / g, one_over_n);
  80. for (int i = 0; i < frames; ++i)
  81. {
  82. register sample_t a = s[i];
  83. a = g * tube.transfer (a * temp);
  84. a = filter.process (a + normal);
  85. a = tube.transfer_clip (up.upsample (a));
  86. a = power_transfer (dc_blocker.process (a));
  87. a = down.process (a);
  88. for (int o = 1; o < OVERSAMPLE; ++o)
  89. down.store (
  90. power_transfer (
  91. dc_blocker.process (
  92. normal + tube.transfer_clip (up.pad (o)))));
  93. F (d, i, a, adding_gain);
  94. g *= gf;
  95. }
  96. current.g = g;
  97. }
  98. /* //////////////////////////////////////////////////////////////////////// */
  99. PortInfo
  100. AmpIII::port_info [] =
  101. {
  102. {
  103. "in",
  104. INPUT | AUDIO,
  105. {BOUNDED, -1, 1}
  106. }, {
  107. "gain",
  108. INPUT | CONTROL,
  109. {BOUNDED | DEFAULT_1, 0, 10}
  110. }, {
  111. "temperature",
  112. INPUT | CONTROL,
  113. {BOUNDED | DEFAULT_MID, 0.005, 1}
  114. }, {
  115. "drive",
  116. INPUT | CONTROL,
  117. {BOUNDED | DEFAULT_MAX, 0.0001, 1} /* ^2 gives the nice drive */
  118. }, {
  119. "out",
  120. OUTPUT | AUDIO,
  121. {0}
  122. }, {
  123. "latency",
  124. OUTPUT | CONTROL,
  125. {0}
  126. }
  127. };
  128. template <> void
  129. Descriptor<AmpIII>::setup()
  130. {
  131. UniqueID = 1786;
  132. Label = "AmpIII";
  133. Properties = HARD_RT;
  134. Name = CAPS "AmpIII - Tube amp";
  135. Maker = "Tim Goetze <tim@quitte.de>";
  136. Copyright = "GPL, 2002-7";
  137. /* fill port info and vtable */
  138. autogen();
  139. }
  140. /* //////////////////////////////////////////////////////////////////////// */
  141. void
  142. AmpIV::init()
  143. {
  144. this->AmpStub::init (false);
  145. /* need to filter out dc before the power amp stage, which is running at
  146. * the oversampled rate */
  147. dc_blocker.set_f (10. / (fs * OVERSAMPLE));
  148. tone.init (fs);
  149. }
  150. template <sample_func_t F, int OVERSAMPLE>
  151. void
  152. AmpIV::one_cycle (int frames)
  153. {
  154. double one_over_n = frames > 0 ? 1. / frames : 1;
  155. sample_t * s = ports[0];
  156. sample_t gain = getport(1);
  157. sample_t temp = getport(2) * tube.scale;
  158. tone.start_cycle (ports + 3, one_over_n);
  159. drive = getport(7) * .5;
  160. i_drive = 1 / (1 - drive);
  161. sample_t * d = ports[8];
  162. *ports[9] = OVERSAMPLE;
  163. double g = current.g;
  164. current.g = max (gain < 1 ? gain : exp2 (gain - 1), .000001);
  165. current.g *= tube.scale / fabs (tube.transfer (temp));
  166. /* recursive fade to prevent zipper noise from the 'gain' knob */
  167. if (g == 0) g = current.g;
  168. double gf = pow (current.g / g, one_over_n);
  169. for (int i = 0; i < frames; ++i)
  170. {
  171. register sample_t a = s[i] + normal;
  172. a = g * tube.transfer (a * temp);
  173. a = tone.process (a);
  174. a = tube.transfer_clip (up.upsample (a));
  175. a = power_transfer (dc_blocker.process (a));
  176. a = down.process (a);
  177. for (int o = 1; o < OVERSAMPLE; ++o)
  178. down.store (
  179. power_transfer (
  180. dc_blocker.process (
  181. normal + tube.transfer_clip (up.pad (o)))));
  182. F (d, i, a, adding_gain);
  183. g *= gf;
  184. }
  185. current.g = g;
  186. }
  187. /* //////////////////////////////////////////////////////////////////////// */
  188. PortInfo
  189. AmpIV::port_info [] =
  190. {
  191. {
  192. "in",
  193. INPUT | AUDIO,
  194. {BOUNDED, -1, 1}
  195. }, {
  196. "gain",
  197. INPUT | CONTROL,
  198. {BOUNDED | DEFAULT_1, 0, 10}
  199. }, {
  200. "temperature",
  201. INPUT | CONTROL,
  202. {BOUNDED | DEFAULT_MID, 0.005, 1}
  203. }, {
  204. "bass",
  205. INPUT | CONTROL,
  206. {BOUNDED | DEFAULT_0, -20, 20}
  207. }, {
  208. "mid",
  209. INPUT | CONTROL,
  210. {BOUNDED | DEFAULT_0, -20, 20}
  211. }, {
  212. "treble",
  213. INPUT | CONTROL,
  214. {BOUNDED | DEFAULT_0, -20, 20}
  215. }, {
  216. "hi",
  217. INPUT | CONTROL,
  218. {BOUNDED | DEFAULT_0, -20, 20}
  219. }, {
  220. "drive",
  221. INPUT | CONTROL,
  222. {BOUNDED | DEFAULT_MAX, 0.0001, 1} /* ^2 gives the nice drive */
  223. }, {
  224. "out",
  225. OUTPUT | AUDIO,
  226. {0}
  227. }, {
  228. "latency",
  229. OUTPUT | CONTROL,
  230. {0}
  231. }
  232. };
  233. template <> void
  234. Descriptor<AmpIV>::setup()
  235. {
  236. UniqueID = 1794;
  237. Label = "AmpIV";
  238. Properties = HARD_RT;
  239. Name = CAPS "AmpIV - Tube amp + tone controls";
  240. Maker = "Tim Goetze <tim@quitte.de>";
  241. Copyright = "GPL, 2002-7";
  242. /* fill port info and vtable */
  243. autogen();
  244. }
  245. /* //////////////////////////////////////////////////////////////////////// */
  246. void
  247. AmpV::init()
  248. {
  249. this->AmpStub::init (false);
  250. /* need to filter out dc before the power amp stage, which is running at
  251. * the oversampled rate */
  252. dc_blocker.set_f (10. / (fs * OVERSAMPLE));
  253. DSP::RBJ::LoShelve (210. / fs, .2, -1, filter[0].a, filter[0].b);
  254. DSP::RBJ::LoShelve (4200. / fs, 1.2, +6, filter[1].a, filter[1].b);
  255. DSP::RBJ::LoShelve (420. / fs, .2, +2, filter[2].a, filter[2].b);
  256. /* power supply cap */
  257. for (int i = 0; i < 2; ++i)
  258. DSP::RBJ::LP (10. / fs, .3, power_cap[i].a, power_cap[i].b);
  259. }
  260. template <sample_func_t F, int OVERSAMPLE>
  261. void
  262. AmpV::one_cycle (int frames)
  263. {
  264. sample_t * s = ports[0];
  265. sample_t gain = getport(1);
  266. if (*ports[2] != cut)
  267. {
  268. cut = getport(2);
  269. DSP::RBJ::LoShelve (210. / fs, .2, cut, filter[0].a, filter[0].b);
  270. }
  271. if (*ports[3] != tone)
  272. {
  273. tone = getport(3);
  274. double f = tone * tone * 8400 + 420;
  275. double q = tone * .4 + .2;
  276. double db = tone * 2 + 2;
  277. DSP::RBJ::LoShelve (f / fs, q, db, filter[2].a, filter[2].b);
  278. }
  279. drive = getport(4) * .5;
  280. i_drive = 1 / (1 - drive);
  281. #define MAX_WATTS port_info[5].range.UpperBound
  282. sample_t sag = (MAX_WATTS - getport(5)) / MAX_WATTS;
  283. sag = .6 * sag * sag;
  284. sample_t * d = ports[6];
  285. *ports[7] = OVERSAMPLE;
  286. double g = current.g;
  287. current.g = max (gain < 1 ? gain : pow (20, gain - 1), .000001);
  288. #if 0
  289. if ( (++_turn & 127) == 0)
  290. fprintf (stderr, "supply = %.3f sag = %.3f\n", supply, sag);
  291. #endif
  292. if (g == 0) g = current.g;
  293. /* recursive fade to prevent zipper noise from the 'gain' knob */
  294. double one_over_n = frames > 0 ? 1. / frames : 1;
  295. double gf = pow (current.g / g, one_over_n);
  296. for (int i = 0; i < frames; ++i)
  297. {
  298. register sample_t a = s[i];
  299. register sample_t v = 3 - supply;
  300. /* alternative curve: v = v * v * .1 + .1; */
  301. v = v * v * .06 + .46;
  302. a = filter[0].process (a + normal);
  303. if (0)
  304. a = filter[2].process (a);
  305. a = g * (a + supply * .001);
  306. a = v * tube.transfer_clip (up.upsample (a));
  307. a = power_transfer (dc_blocker.process (a));
  308. a = down.process (a);
  309. a = filter[1].process (a - normal);
  310. if (1)
  311. a = filter[2].process (a + normal);
  312. {
  313. for (int o = 1; o < OVERSAMPLE; ++o)
  314. down.store (
  315. power_transfer (
  316. dc_blocker.process (
  317. normal + tube.transfer_clip (
  318. up.pad (o)))));
  319. }
  320. F (d, i, a, adding_gain);
  321. /* integrate for an approximation of cumulative output power */
  322. supply += sag * fabs (a) + normal;
  323. /* filter integrated power consumption */
  324. for (int j = 0; j < 2; ++j)
  325. supply = 0.9 * (power_cap[j].process (supply));
  326. g *= gf;
  327. normal = -normal;
  328. }
  329. current.g = g;
  330. }
  331. /* //////////////////////////////////////////////////////////////////////// */
  332. PortInfo
  333. AmpV::port_info [] =
  334. {
  335. {
  336. "in",
  337. INPUT | AUDIO,
  338. {BOUNDED, -1, 1}
  339. }, {
  340. "gain",
  341. INPUT | CONTROL,
  342. {BOUNDED | DEFAULT_1, 0, 3}
  343. }, {
  344. "bass",
  345. INPUT | CONTROL,
  346. {BOUNDED | DEFAULT_0, -9, 9}
  347. }, {
  348. "tone",
  349. INPUT | CONTROL,
  350. {BOUNDED | DEFAULT_MIN, 0, 1}
  351. }, {
  352. "drive",
  353. INPUT | CONTROL,
  354. {BOUNDED | DEFAULT_HIGH, 0.0001, 1} /* ^2 gives the nice drive */
  355. }, {
  356. "watts",
  357. INPUT | CONTROL,
  358. {BOUNDED | DEFAULT_MID, 5, 150}
  359. }, {
  360. "out",
  361. OUTPUT | AUDIO,
  362. {0}
  363. }, {
  364. "latency",
  365. OUTPUT | CONTROL,
  366. {0}
  367. }
  368. };
  369. template <> void
  370. Descriptor<AmpV>::setup()
  371. {
  372. UniqueID = 2587;
  373. Label = "AmpV";
  374. Properties = HARD_RT;
  375. Name = CAPS "AmpV - Tube amp";
  376. Maker = "Tim Goetze <tim@quitte.de>";
  377. Copyright = "GPL, 2002-7";
  378. /* fill port info and vtable */
  379. autogen();
  380. }
  381. /* //////////////////////////////////////////////////////////////////////// */
  382. void
  383. AmpVTS::init()
  384. {
  385. this->AmpStub::init (false);
  386. /* need to filter out dc before the power amp stage, which is running at
  387. * the oversampled rate */
  388. dc_blocker.set_f (10. / (fs * OVERSAMPLE));
  389. /* power supply capacitance */
  390. for (int i = 0; i < 2; ++i)
  391. DSP::RBJ::LP (10. / fs, .3, power_cap[i].a, power_cap[i].b);
  392. tonestack.init (fs);
  393. }
  394. template <sample_func_t F, int OVERSAMPLE>
  395. void
  396. AmpVTS::one_cycle (int frames)
  397. {
  398. sample_t * s = ports[0];
  399. tonestack.start_cycle (ports + 1, 2);
  400. sample_t gain = getport(2);
  401. drive = getport(6) * .5;
  402. i_drive = 1 / (1 - drive);
  403. sample_t sag = 1 - max (0.0001, min (1, getport(7)));
  404. sag = .6 * sag * sag; /* map to log space makes slider better */
  405. sample_t * d = ports[8];
  406. *ports[9] = OVERSAMPLE;
  407. double g = current.g;
  408. if (gain < 1)
  409. current.g = max (gain, .001);
  410. else
  411. {
  412. gain -= 1;
  413. gain *= gain;
  414. current.g = pow (10, gain);
  415. }
  416. /* recursive fade to prevent zipper noise from the 'gain' knob */
  417. double one_over_n = frames > 0 ? 1. / frames : 1;
  418. double gf = pow (current.g / g, one_over_n);
  419. for (int i = 0; i < frames; ++i)
  420. {
  421. register double a = s[i];
  422. register double v = 3 - supply;
  423. v = v * v * .06 + .46;
  424. a = tube.transfer (a);
  425. a = tonestack.process (a + normal);
  426. a = g * (a + supply * .001);
  427. a = v * tube.transfer_clip (up.upsample (a));
  428. a = power_transfer (dc_blocker.process (a));
  429. a = down.process (a);
  430. {
  431. for (int o = 1; o < OVERSAMPLE; ++o)
  432. down.store (
  433. power_transfer (
  434. dc_blocker.process (
  435. normal + tube.transfer_clip (
  436. up.pad (o)))));
  437. }
  438. F (d, i, a, adding_gain);
  439. /* integrate for an approximation of cumulative output power */
  440. supply += sag * fabs (a) + normal;
  441. /* filter integrated power consumption */
  442. for (int j = 0; j < 2; ++j)
  443. supply = 0.9 * (power_cap[j].process (supply + normal));
  444. g *= gf;
  445. normal = -normal;
  446. }
  447. current.g = g;
  448. }
  449. /* //////////////////////////////////////////////////////////////////////// */
  450. PortInfo
  451. AmpVTS::port_info [] =
  452. {
  453. {
  454. "in",
  455. INPUT | AUDIO,
  456. {BOUNDED, -1, 1}
  457. }, {
  458. "model",
  459. INPUT | CONTROL,
  460. {BOUNDED | DEFAULT_0 | INTEGER, 0, 5} /* no way to set dyn at compile t */
  461. }, {
  462. "gain",
  463. INPUT | CONTROL,
  464. {BOUNDED | DEFAULT_HIGH, 0, 3}
  465. }, {
  466. "bass",
  467. INPUT | CONTROL,
  468. {BOUNDED | DEFAULT_MID, 0, 1}
  469. }, {
  470. "mid",
  471. INPUT | CONTROL,
  472. {BOUNDED | DEFAULT_1, 0, 1}
  473. }, {
  474. "treble",
  475. INPUT | CONTROL,
  476. {BOUNDED | DEFAULT_HIGH, 0, 1}
  477. }, {
  478. "drive",
  479. INPUT | CONTROL,
  480. {BOUNDED | DEFAULT_LOW, 0.0001, 1}
  481. }, {
  482. "watts",
  483. INPUT | CONTROL,
  484. {BOUNDED | DEFAULT_HIGH, 0.0001, 1}
  485. }, {
  486. "out",
  487. OUTPUT | AUDIO,
  488. {0}
  489. }, {
  490. "latency",
  491. OUTPUT | CONTROL,
  492. {0}
  493. }
  494. };
  495. template <> void
  496. Descriptor<AmpVTS>::setup()
  497. {
  498. UniqueID = 2592;
  499. Label = "AmpVTS";
  500. Properties = HARD_RT;
  501. Name = CAPS "AmpVTS - Tube amp + Tone stack";
  502. Maker = "David Yeh <dtyeh@ccrma.stanford.edu> & Tim Goetze <tim@quitte.de>";
  503. Copyright = "GPL, 2002-7";
  504. /* fill port info and vtable */
  505. autogen();
  506. }