Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SUBnote.cpp 18KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. SUBnote.cpp - The "subtractive" synthesizer
  4. Copyright (C) 2002-2005 Nasca Octavian Paul
  5. Author: Nasca Octavian Paul
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. */
  11. #include <cmath>
  12. #include <cstdlib>
  13. #include <cstdio>
  14. #include <cassert>
  15. #include <iostream>
  16. #include "../globals.h"
  17. #include "SUBnote.h"
  18. #include "Envelope.h"
  19. #include "ModFilter.h"
  20. #include "../Containers/ScratchString.h"
  21. #include "../Params/Controller.h"
  22. #include "../Params/SUBnoteParameters.h"
  23. #include "../Params/FilterParams.h"
  24. #include "../Misc/Time.h"
  25. #include "../Misc/Util.h"
  26. #include "../Misc/Allocator.h"
  27. #ifndef M_PI
  28. # define M_PI 3.14159265358979323846 /* pi */
  29. #endif
  30. namespace zyncarla {
  31. SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars)
  32. :SynthNote(spars), pars(*parameters),
  33. AmpEnvelope(nullptr),
  34. FreqEnvelope(nullptr),
  35. BandWidthEnvelope(nullptr),
  36. GlobalFilter(nullptr),
  37. GlobalFilterEnvelope(nullptr),
  38. NoteEnabled(true),
  39. lfilter(nullptr), rfilter(nullptr),
  40. wm(nullptr)
  41. {
  42. setup(spars.frequency, spars.velocity, spars.portamento, spars.note);
  43. }
  44. float SUBnote::setupFilters(int *pos, bool automation)
  45. {
  46. //how much the amplitude is normalised (because the harmonics)
  47. float reduceamp = 0.0f;
  48. for(int n = 0; n < numharmonics; ++n) {
  49. const float freq = basefreq * pars.POvertoneFreqMult[pos[n]];
  50. overtone_freq[n] = freq;
  51. overtone_rolloff[n] = computerolloff(freq);
  52. //the bandwidth is not absolute(Hz); it is relative to frequency
  53. const float bw = SUBnoteParameters::convertBandwidth(pars.Pbandwidth,
  54. numstages, freq, pars.Pbwscale, pars.Phrelbw[pos[n]]);
  55. //try to keep same amplitude on all freqs and bw. (empirically)
  56. const float hgain = SUBnoteParameters::convertHarmonicMag(pars.Phmag[pos[n]],
  57. pars.Phmagtype);
  58. const float gain = hgain * sqrt(1500.0f / (bw * freq));
  59. reduceamp += hgain;
  60. for(int nph = 0; nph < numstages; ++nph) {
  61. float amp = 1.0f;
  62. if(nph == 0)
  63. amp = gain;
  64. initfilter(lfilter[nph + n * numstages], freq + OffsetHz, bw,
  65. amp, hgain, automation);
  66. if(stereo)
  67. initfilter(rfilter[nph + n * numstages], freq + OffsetHz, bw,
  68. amp, hgain, automation);
  69. }
  70. }
  71. if(reduceamp < 0.001f)
  72. reduceamp = 1.0f;
  73. return reduceamp;
  74. }
  75. void SUBnote::setup(float freq,
  76. float velocity,
  77. int portamento_,
  78. int midinote,
  79. bool legato)
  80. {
  81. this->velocity = velocity;
  82. portamento = portamento_;
  83. NoteEnabled = ON;
  84. volume = powf(0.1f, 3.0f * (1.0f - pars.PVolume / 96.0f)); //-60 dB .. 0 dB
  85. volume *= VelF(velocity, pars.PAmpVelocityScaleFunction);
  86. if(pars.PPanning != 0)
  87. panning = pars.PPanning / 127.0f;
  88. else
  89. panning = RND;
  90. if(!legato) { //normal note
  91. numstages = pars.Pnumstages;
  92. stereo = pars.Pstereo;
  93. start = pars.Pstart;
  94. firsttick = 1;
  95. }
  96. if(pars.Pfixedfreq == 0)
  97. basefreq = freq;
  98. else {
  99. basefreq = 440.0f;
  100. int fixedfreqET = pars.PfixedfreqET;
  101. if(fixedfreqET) { //if the frequency varies according the keyboard note
  102. float tmp = (midinote - 69.0f) / 12.0f
  103. * (powf(2.0f, (fixedfreqET - 1) / 63.0f) - 1.0f);
  104. if(fixedfreqET <= 64)
  105. basefreq *= powf(2.0f, tmp);
  106. else
  107. basefreq *= powf(3.0f, tmp);
  108. }
  109. }
  110. int BendAdj = pars.PBendAdjust - 64;
  111. if (BendAdj % 24 == 0)
  112. BendAdjust = BendAdj / 24;
  113. else
  114. BendAdjust = BendAdj / 24.0f;
  115. float offset_val = (pars.POffsetHz - 64)/64.0f;
  116. OffsetHz = 15.0f*(offset_val * sqrtf(fabsf(offset_val)));
  117. float detune = getdetune(pars.PDetuneType,
  118. pars.PCoarseDetune,
  119. pars.PDetune);
  120. basefreq *= powf(2.0f, detune / 1200.0f); //detune
  121. // basefreq*=ctl.pitchwheel.relfreq;//pitch wheel
  122. int pos[MAX_SUB_HARMONICS];
  123. int harmonics;
  124. pars.activeHarmonics(pos, harmonics);
  125. if(!legato) //normal note
  126. firstnumharmonics = numharmonics = harmonics;
  127. else {
  128. if(harmonics > firstnumharmonics)
  129. numharmonics = firstnumharmonics;
  130. else
  131. numharmonics = harmonics;
  132. }
  133. if(numharmonics == 0) {
  134. NoteEnabled = false;
  135. return;
  136. }
  137. if(!legato) { //normal note
  138. lfilter = memory.valloc<bpfilter>(numstages * numharmonics);
  139. if(stereo)
  140. rfilter = memory.valloc<bpfilter>(numstages * numharmonics);
  141. }
  142. //how much the amplitude is normalised (because the harmonics)
  143. float reduceamp = setupFilters(pos, false);
  144. oldreduceamp = reduceamp;
  145. volume /= reduceamp;
  146. oldpitchwheel = 0;
  147. oldbandwidth = 64;
  148. if(!legato) { //normal note
  149. if(pars.Pfixedfreq == 0)
  150. initparameters(basefreq, wm);
  151. else
  152. initparameters(basefreq / 440.0f * freq, wm);
  153. }
  154. else {
  155. if(pars.Pfixedfreq == 0)
  156. freq = basefreq;
  157. else
  158. freq *= basefreq / 440.0f;
  159. if(GlobalFilter)
  160. GlobalFilter->updateNoteFreq(basefreq);
  161. }
  162. oldamplitude = newamplitude;
  163. }
  164. SynthNote *SUBnote::cloneLegato(void)
  165. {
  166. SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity,
  167. portamento, legato.param.midinote, true};
  168. return memory.alloc<SUBnote>(&pars, sp);
  169. }
  170. void SUBnote::legatonote(LegatoParams pars)
  171. {
  172. // Manage legato stuff
  173. if(legato.update(pars))
  174. return;
  175. try {
  176. setup(pars.frequency, pars.velocity, pars.portamento, pars.midinote,
  177. true);
  178. } catch (std::bad_alloc &ba) {
  179. std::cerr << "failed to set legato note parameter in SUBnote: " << ba.what() << std::endl;
  180. }
  181. }
  182. SUBnote::~SUBnote()
  183. {
  184. if(NoteEnabled)
  185. KillNote();
  186. }
  187. /*
  188. * Kill the note
  189. */
  190. void SUBnote::KillNote()
  191. {
  192. if(NoteEnabled) {
  193. memory.devalloc(numstages * numharmonics, lfilter);
  194. if(stereo)
  195. memory.devalloc(numstages * numharmonics, rfilter);
  196. memory.dealloc(AmpEnvelope);
  197. memory.dealloc(FreqEnvelope);
  198. memory.dealloc(BandWidthEnvelope);
  199. memory.dealloc(GlobalFilter);
  200. memory.dealloc(GlobalFilterEnvelope);
  201. NoteEnabled = false;
  202. }
  203. }
  204. /*
  205. * Compute the filters coefficients
  206. */
  207. void SUBnote::computefiltercoefs(bpfilter &filter,
  208. float freq,
  209. float bw,
  210. float gain)
  211. {
  212. if(freq > synth.samplerate_f / 2.0f - 200.0f)
  213. freq = synth.samplerate_f / 2.0f - 200.0f;
  214. float omega = 2.0f * PI * freq / synth.samplerate_f;
  215. float sn = sinf(omega);
  216. float cs = cosf(omega);
  217. float alpha = sn * sinh(LOG_2 / 2.0f * bw * omega / sn);
  218. if(alpha > 1)
  219. alpha = 1;
  220. if(alpha > bw)
  221. alpha = bw;
  222. filter.b0 = alpha / (1.0f + alpha) * filter.amp * gain;
  223. filter.b2 = -alpha / (1.0f + alpha) * filter.amp * gain;
  224. filter.a1 = -2.0f * cs / (1.0f + alpha);
  225. filter.a2 = (1.0f - alpha) / (1.0f + alpha);
  226. }
  227. /*
  228. * Initialise the filters
  229. */
  230. void SUBnote::initfilter(bpfilter &filter,
  231. float freq,
  232. float bw,
  233. float amp,
  234. float mag,
  235. bool automation)
  236. {
  237. if(!automation) {
  238. filter.xn1 = 0.0f;
  239. filter.xn2 = 0.0f;
  240. if(start == 0) {
  241. filter.yn1 = 0.0f;
  242. filter.yn2 = 0.0f;
  243. }
  244. else {
  245. float a = 0.1f * mag; //empirically
  246. float p = RND * 2.0f * PI;
  247. if(start == 1)
  248. a *= RND;
  249. filter.yn1 = a * cosf(p);
  250. filter.yn2 = a * cosf(p + freq * 2.0f * PI / synth.samplerate_f);
  251. //correct the error of computation the start amplitude
  252. //at very high frequencies
  253. if(freq > synth.samplerate_f * 0.96f) {
  254. filter.yn1 = 0.0f;
  255. filter.yn2 = 0.0f;
  256. }
  257. }
  258. }
  259. filter.amp = amp;
  260. filter.freq = freq;
  261. filter.bw = bw;
  262. computefiltercoefs(filter, freq, bw, 1.0f);
  263. }
  264. /*
  265. * Do the filtering
  266. */
  267. inline void SubFilterA(const float coeff[4], float &src, float work[4])
  268. {
  269. work[3] = src*coeff[0]+work[1]*coeff[1]+work[2]*coeff[2]+work[3]*coeff[3];
  270. work[1] = src;
  271. src = work[3];
  272. }
  273. inline void SubFilterB(const float coeff[4], float &src, float work[4])
  274. {
  275. work[2] = src*coeff[0]+work[0]*coeff[1]+work[3]*coeff[2]+work[2]*coeff[3];
  276. work[0] = src;
  277. src = work[2];
  278. }
  279. //This dance is designed to minimize unneeded memory operations which can result
  280. //in quite a bit of wasted time
  281. void SUBnote::filter(bpfilter &filter, float *smps)
  282. {
  283. assert(synth.buffersize % 8 == 0);
  284. float coeff[4] = {filter.b0, filter.b2, -filter.a1, -filter.a2};
  285. float work[4] = {filter.xn1, filter.xn2, filter.yn1, filter.yn2};
  286. for(int i = 0; i < synth.buffersize; i += 8) {
  287. SubFilterA(coeff, smps[i + 0], work);
  288. SubFilterB(coeff, smps[i + 1], work);
  289. SubFilterA(coeff, smps[i + 2], work);
  290. SubFilterB(coeff, smps[i + 3], work);
  291. SubFilterA(coeff, smps[i + 4], work);
  292. SubFilterB(coeff, smps[i + 5], work);
  293. SubFilterA(coeff, smps[i + 6], work);
  294. SubFilterB(coeff, smps[i + 7], work);
  295. }
  296. filter.xn1 = work[0];
  297. filter.xn2 = work[1];
  298. filter.yn1 = work[2];
  299. filter.yn2 = work[3];
  300. }
  301. /*
  302. * Init Parameters
  303. */
  304. void SUBnote::initparameters(float freq, WatchManager *wm)
  305. {
  306. //TODO populate this base string
  307. ScratchString pre;
  308. AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, freq,
  309. synth.dt(), wm, (pre+"AmpEnvelope/").c_str);
  310. if(pars.PFreqEnvelopeEnabled)
  311. FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, freq,
  312. synth.dt(), wm, (pre+"FreqEnvelope/").c_str);
  313. if(pars.PBandWidthEnvelopeEnabled)
  314. BandWidthEnvelope = memory.alloc<Envelope>(*pars.BandWidthEnvelope,
  315. freq, synth.dt(), wm, (pre+"BandWidthEnvelope/").c_str);
  316. if(pars.PGlobalFilterEnabled) {
  317. GlobalFilterEnvelope =
  318. memory.alloc<Envelope>(*pars.GlobalFilterEnvelope, freq,
  319. synth.dt(), wm, (pre+"GlobalFilterEnvelope/").c_str);
  320. GlobalFilter = memory.alloc<ModFilter>(*pars.GlobalFilter, synth, time, memory, stereo, freq);
  321. GlobalFilter->updateSense(velocity, pars.PGlobalFilterVelocityScale,
  322. pars.PGlobalFilterVelocityScaleFunction);
  323. GlobalFilter->addMod(*GlobalFilterEnvelope);
  324. }
  325. computecurrentparameters();
  326. }
  327. /*
  328. * Compute how much to reduce amplitude near nyquist or subaudible frequencies.
  329. */
  330. float SUBnote::computerolloff(float freq)
  331. {
  332. const float lower_limit = 10.0f;
  333. const float lower_width = 10.0f;
  334. const float upper_width = 200.0f;
  335. float upper_limit = synth.samplerate / 2.0f;
  336. if (freq > lower_limit + lower_width &&
  337. freq < upper_limit - upper_width)
  338. return 1.0f;
  339. if (freq <= lower_limit || freq >= upper_limit)
  340. return 0.0f;
  341. if (freq <= lower_limit + lower_width)
  342. return (1.0f - cosf(M_PI * (freq - lower_limit) / lower_width)) / 2.0f;
  343. return (1.0f - cosf(M_PI * (freq - upper_limit) / upper_width)) / 2.0f;
  344. }
  345. /*
  346. * Compute Parameters of SUBnote for each tick
  347. */
  348. void SUBnote::computecurrentparameters()
  349. {
  350. //Recompute parameters for realtime automation
  351. if(pars.time && pars.last_update_timestamp == pars.time->time()) {
  352. //A little bit of copy/paste for now
  353. int pos[MAX_SUB_HARMONICS];
  354. int harmonics;
  355. pars.activeHarmonics(pos, harmonics);
  356. bool delta_harmonics = (harmonics != numharmonics);
  357. if(delta_harmonics) {
  358. memory.devalloc(lfilter);
  359. memory.devalloc(rfilter);
  360. firstnumharmonics = numharmonics = harmonics;
  361. lfilter = memory.valloc<bpfilter>(numstages * numharmonics);
  362. if(stereo)
  363. rfilter = memory.valloc<bpfilter>(numstages * numharmonics);
  364. }
  365. float reduceamp = setupFilters(pos, !delta_harmonics);
  366. volume = volume*oldreduceamp/reduceamp;
  367. oldreduceamp = reduceamp;
  368. }
  369. if(FreqEnvelope || BandWidthEnvelope
  370. || (oldpitchwheel != ctl.pitchwheel.data)
  371. || (oldbandwidth != ctl.bandwidth.data)
  372. || portamento) {
  373. float envfreq = 1.0f;
  374. float envbw = 1.0f;
  375. if(FreqEnvelope) {
  376. envfreq = FreqEnvelope->envout() / 1200;
  377. envfreq = powf(2.0f, envfreq);
  378. }
  379. envfreq *=
  380. powf(ctl.pitchwheel.relfreq, BendAdjust); //pitch wheel
  381. //Update frequency while portamento is converging
  382. if(portamento) {
  383. envfreq *= ctl.portamento.freqrap;
  384. if(!ctl.portamento.used) //the portamento has finished
  385. portamento = false;
  386. }
  387. if(BandWidthEnvelope) {
  388. envbw = BandWidthEnvelope->envout();
  389. envbw = powf(2, envbw);
  390. }
  391. envbw *= ctl.bandwidth.relbw; //bandwidth controller
  392. //Recompute High Frequency Dampening Terms
  393. for(int n = 0; n < numharmonics; ++n)
  394. overtone_rolloff[n] = computerolloff(overtone_freq[n] * envfreq);
  395. //Recompute Filter Coefficients
  396. float tmpgain = 1.0f / sqrt(envbw * envfreq);
  397. computeallfiltercoefs(lfilter, envfreq, envbw, tmpgain);
  398. if(stereo)
  399. computeallfiltercoefs(rfilter, envfreq, envbw, tmpgain);
  400. oldbandwidth = ctl.bandwidth.data;
  401. oldpitchwheel = ctl.pitchwheel.data;
  402. }
  403. newamplitude = volume * AmpEnvelope->envout_dB() * 2.0f;
  404. //Filter
  405. if(GlobalFilter)
  406. GlobalFilter->update(ctl.filtercutoff.relfreq,
  407. ctl.filterq.relq);
  408. }
  409. void SUBnote::computeallfiltercoefs(bpfilter *filters, float envfreq,
  410. float envbw, float gain)
  411. {
  412. for(int n = 0; n < numharmonics; ++n)
  413. for(int nph = 0; nph < numstages; ++nph)
  414. computefiltercoefs(filters[nph + n * numstages],
  415. filters[nph + n * numstages].freq * envfreq,
  416. filters[nph + n * numstages].bw * envbw,
  417. nph == 0 ? gain : 1.0);
  418. }
  419. void SUBnote::chanOutput(float *out, bpfilter *bp, int buffer_size)
  420. {
  421. float tmprnd[buffer_size];
  422. float tmpsmp[buffer_size];
  423. //Initialize Random Input
  424. for(int i = 0; i < buffer_size; ++i)
  425. tmprnd[i] = RND * 2.0f - 1.0f;
  426. //For each harmonic apply the filter on the random input stream
  427. //Sum the filter outputs to obtain the output signal
  428. for(int n = 0; n < numharmonics; ++n) {
  429. float rolloff = overtone_rolloff[n];
  430. memcpy(tmpsmp, tmprnd, synth.bufferbytes);
  431. for(int nph = 0; nph < numstages; ++nph)
  432. filter(bp[nph + n * numstages], tmpsmp);
  433. for(int i = 0; i < synth.buffersize; ++i)
  434. out[i] += tmpsmp[i] * rolloff;
  435. }
  436. }
  437. /*
  438. * Note Output
  439. */
  440. int SUBnote::noteout(float *outl, float *outr)
  441. {
  442. memcpy(outl, synth.denormalkillbuf, synth.bufferbytes);
  443. memcpy(outr, synth.denormalkillbuf, synth.bufferbytes);
  444. if(!NoteEnabled)
  445. return 0;
  446. if(stereo) {
  447. chanOutput(outl, lfilter, synth.buffersize);
  448. chanOutput(outr, rfilter, synth.buffersize);
  449. if(GlobalFilter)
  450. GlobalFilter->filter(outl, outr);
  451. } else {
  452. chanOutput(outl, lfilter, synth.buffersize);
  453. if(GlobalFilter)
  454. GlobalFilter->filter(outl, 0);
  455. memcpy(outr, outl, synth.bufferbytes);
  456. }
  457. if(firsttick) {
  458. int n = 10;
  459. if(n > synth.buffersize)
  460. n = synth.buffersize;
  461. for(int i = 0; i < n; ++i) {
  462. float ampfadein = 0.5f - 0.5f * cosf(
  463. (float) i / (float) n * PI);
  464. outl[i] *= ampfadein;
  465. outr[i] *= ampfadein;
  466. }
  467. firsttick = false;
  468. }
  469. if(ABOVE_AMPLITUDE_THRESHOLD(oldamplitude, newamplitude))
  470. // Amplitude interpolation
  471. for(int i = 0; i < synth.buffersize; ++i) {
  472. float tmpvol = INTERPOLATE_AMPLITUDE(oldamplitude,
  473. newamplitude,
  474. i,
  475. synth.buffersize);
  476. outl[i] *= tmpvol * panning;
  477. outr[i] *= tmpvol * (1.0f - panning);
  478. }
  479. else
  480. for(int i = 0; i < synth.buffersize; ++i) {
  481. outl[i] *= newamplitude * panning;
  482. outr[i] *= newamplitude * (1.0f - panning);
  483. }
  484. oldamplitude = newamplitude;
  485. computecurrentparameters();
  486. // Apply legato-specific sound signal modifications
  487. legato.apply(*this, outl, outr);
  488. // Check if the note needs to be computed more
  489. if(AmpEnvelope->finished() != 0) {
  490. for(int i = 0; i < synth.buffersize; ++i) { //fade-out
  491. float tmp = 1.0f - (float)i / synth.buffersize_f;
  492. outl[i] *= tmp;
  493. outr[i] *= tmp;
  494. }
  495. KillNote();
  496. }
  497. return 1;
  498. }
  499. /*
  500. * Release Key (Note Off)
  501. */
  502. void SUBnote::releasekey()
  503. {
  504. AmpEnvelope->releasekey();
  505. if(FreqEnvelope)
  506. FreqEnvelope->releasekey();
  507. if(BandWidthEnvelope)
  508. BandWidthEnvelope->releasekey();
  509. if(GlobalFilterEnvelope)
  510. GlobalFilterEnvelope->releasekey();
  511. }
  512. /*
  513. * Check if the note is finished
  514. */
  515. bool SUBnote::finished() const
  516. {
  517. return !NoteEnabled;
  518. }
  519. void SUBnote::entomb(void)
  520. {
  521. AmpEnvelope->forceFinish();
  522. }
  523. }