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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  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 modify
  7. it under the terms of version 2 of the GNU General Public License
  8. as published by the Free Software Foundation.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License (version 2 or later) for more details.
  13. You should have received a copy of the GNU General Public License (version 2)
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. #include <cmath>
  18. #include <cstdlib>
  19. #include <cstdio>
  20. #include <cassert>
  21. #include "../globals.h"
  22. #include "SUBnote.h"
  23. #include "../Misc/Util.h"
  24. SUBnote::SUBnote(SUBnoteParameters *parameters,
  25. Controller *ctl_,
  26. float freq,
  27. float velocity,
  28. int portamento_,
  29. int midinote,
  30. bool besilent)
  31. :SynthNote(freq, velocity, portamento_, midinote, besilent)
  32. {
  33. pars = parameters;
  34. ctl = ctl_;
  35. NoteEnabled = ON;
  36. setup(freq, velocity, portamento_, midinote);
  37. }
  38. void SUBnote::setup(float freq,
  39. float velocity,
  40. int portamento_,
  41. int midinote,
  42. bool legato)
  43. {
  44. portamento = portamento_;
  45. NoteEnabled = ON;
  46. volume = powf(0.1f, 3.0f * (1.0f - pars->PVolume / 96.0f)); //-60 dB .. 0 dB
  47. volume *= VelF(velocity, pars->PAmpVelocityScaleFunction);
  48. if(pars->PPanning != 0)
  49. panning = pars->PPanning / 127.0f;
  50. else
  51. panning = RND;
  52. if(!legato) {
  53. numstages = pars->Pnumstages;
  54. stereo = pars->Pstereo;
  55. start = pars->Pstart;
  56. firsttick = 1;
  57. }
  58. int pos[MAX_SUB_HARMONICS];
  59. if(pars->Pfixedfreq == 0)
  60. basefreq = freq;
  61. else {
  62. basefreq = 440.0f;
  63. int fixedfreqET = pars->PfixedfreqET;
  64. if(fixedfreqET != 0) { //if the frequency varies according the keyboard note
  65. float tmp =
  66. (midinote
  67. - 69.0f) / 12.0f
  68. * (powf(2.0f, (fixedfreqET - 1) / 63.0f) - 1.0f);
  69. if(fixedfreqET <= 64)
  70. basefreq *= powf(2.0f, tmp);
  71. else
  72. basefreq *= powf(3.0f, tmp);
  73. }
  74. }
  75. float detune = getdetune(pars->PDetuneType,
  76. pars->PCoarseDetune,
  77. pars->PDetune);
  78. basefreq *= powf(2.0f, detune / 1200.0f); //detune
  79. // basefreq*=ctl->pitchwheel.relfreq;//pitch wheel
  80. //global filter
  81. GlobalFilterCenterPitch = pars->GlobalFilter->getfreq() //center freq
  82. + (pars->PGlobalFilterVelocityScale / 127.0f
  83. * 6.0f) //velocity sensing
  84. * (VelF(velocity,
  85. pars->PGlobalFilterVelocityScaleFunction)
  86. - 1);
  87. if(!legato) {
  88. GlobalFilterL = NULL;
  89. GlobalFilterR = NULL;
  90. GlobalFilterEnvelope = NULL;
  91. }
  92. int harmonics = 0;
  93. //select only harmonics that desire to compute
  94. for(int n = 0; n < MAX_SUB_HARMONICS; ++n) {
  95. if(pars->Phmag[n] == 0)
  96. continue;
  97. pos[harmonics++] = n;
  98. }
  99. if(!legato)
  100. firstnumharmonics = numharmonics = harmonics;
  101. else {
  102. if(harmonics > firstnumharmonics)
  103. numharmonics = firstnumharmonics;
  104. else
  105. numharmonics = harmonics;
  106. }
  107. if(numharmonics == 0) {
  108. NoteEnabled = OFF;
  109. return;
  110. }
  111. if(!legato) {
  112. lfilter = new bpfilter[numstages * numharmonics];
  113. if(stereo != 0)
  114. rfilter = new bpfilter[numstages * numharmonics];
  115. }
  116. //how much the amplitude is normalised (because the harmonics)
  117. float reduceamp = 0.0f;
  118. for(int n = 0; n < numharmonics; ++n) {
  119. float freq = basefreq * pars->POvertoneFreqMult[pos[n]];
  120. overtone_freq[n] = freq;
  121. overtone_rolloff[n] = computerolloff(freq);
  122. //the bandwidth is not absolute(Hz); it is relative to frequency
  123. float bw =
  124. powf(10, (pars->Pbandwidth - 127.0f) / 127.0f * 4) * numstages;
  125. //Bandwidth Scale
  126. bw *= powf(1000 / freq, (pars->Pbwscale - 64.0f) / 64.0f * 3.0f);
  127. //Relative BandWidth
  128. bw *= powf(100, (pars->Phrelbw[pos[n]] - 64.0f) / 64.0f);
  129. if(bw > 25.0f)
  130. bw = 25.0f;
  131. //try to keep same amplitude on all freqs and bw. (empirically)
  132. float gain = sqrt(1500.0f / (bw * freq));
  133. float hmagnew = 1.0f - pars->Phmag[pos[n]] / 127.0f;
  134. float hgain;
  135. switch(pars->Phmagtype) {
  136. case 1:
  137. hgain = expf(hmagnew * logf(0.01f));
  138. break;
  139. case 2:
  140. hgain = expf(hmagnew * logf(0.001f));
  141. break;
  142. case 3:
  143. hgain = expf(hmagnew * logf(0.0001f));
  144. break;
  145. case 4:
  146. hgain = expf(hmagnew * logf(0.00001f));
  147. break;
  148. default:
  149. hgain = 1.0f - hmagnew;
  150. }
  151. gain *= hgain;
  152. reduceamp += hgain;
  153. for(int nph = 0; nph < numstages; ++nph) {
  154. float amp = 1.0f;
  155. if(nph == 0)
  156. amp = gain;
  157. initfilter(lfilter[nph + n * numstages], freq, bw, amp, hgain);
  158. if(stereo != 0)
  159. initfilter(rfilter[nph + n * numstages], freq, bw, amp, hgain);
  160. }
  161. }
  162. if(reduceamp < 0.001f)
  163. reduceamp = 1.0f;
  164. volume /= reduceamp;
  165. oldpitchwheel = 0;
  166. oldbandwidth = 64;
  167. if(!legato) {
  168. if(pars->Pfixedfreq == 0)
  169. initparameters(basefreq);
  170. else
  171. initparameters(basefreq / 440.0f * freq);
  172. }
  173. else {
  174. if(pars->Pfixedfreq == 0)
  175. freq = basefreq;
  176. else
  177. freq *= basefreq / 440.0f;
  178. if(pars->PGlobalFilterEnabled != 0) {
  179. globalfiltercenterq = pars->GlobalFilter->getq();
  180. GlobalFilterFreqTracking = pars->GlobalFilter->getfreqtracking(
  181. basefreq);
  182. }
  183. }
  184. oldamplitude = newamplitude;
  185. }
  186. void SUBnote::legatonote(float freq, float velocity, int portamento_,
  187. int midinote, bool externcall)
  188. {
  189. // Manage legato stuff
  190. if(legato.update(freq, velocity, portamento_, midinote, externcall))
  191. return;
  192. setup(freq, velocity, portamento_, midinote, true);
  193. }
  194. SUBnote::~SUBnote()
  195. {
  196. if(NoteEnabled != OFF)
  197. KillNote();
  198. }
  199. /*
  200. * Kill the note
  201. */
  202. void SUBnote::KillNote()
  203. {
  204. if(NoteEnabled != OFF) {
  205. delete [] lfilter;
  206. lfilter = NULL;
  207. if(stereo != 0)
  208. delete [] rfilter;
  209. rfilter = NULL;
  210. delete AmpEnvelope;
  211. delete FreqEnvelope;
  212. delete BandWidthEnvelope;
  213. delete GlobalFilterL;
  214. delete GlobalFilterR;
  215. delete GlobalFilterEnvelope;
  216. NoteEnabled = OFF;
  217. }
  218. }
  219. /*
  220. * Compute the filters coefficients
  221. */
  222. void SUBnote::computefiltercoefs(bpfilter &filter,
  223. float freq,
  224. float bw,
  225. float gain)
  226. {
  227. if(freq > synth->samplerate_f / 2.0f - 200.0f)
  228. freq = synth->samplerate_f / 2.0f - 200.0f;
  229. float omega = 2.0f * PI * freq / synth->samplerate_f;
  230. float sn = sinf(omega);
  231. float cs = cosf(omega);
  232. float alpha = sn * sinh(LOG_2 / 2.0f * bw * omega / sn);
  233. if(alpha > 1)
  234. alpha = 1;
  235. if(alpha > bw)
  236. alpha = bw;
  237. filter.b0 = alpha / (1.0f + alpha) * filter.amp * gain;
  238. filter.b2 = -alpha / (1.0f + alpha) * filter.amp * gain;
  239. filter.a1 = -2.0f * cs / (1.0f + alpha);
  240. filter.a2 = (1.0f - alpha) / (1.0f + alpha);
  241. }
  242. /*
  243. * Initialise the filters
  244. */
  245. void SUBnote::initfilter(bpfilter &filter,
  246. float freq,
  247. float bw,
  248. float amp,
  249. float mag)
  250. {
  251. filter.xn1 = 0.0f;
  252. filter.xn2 = 0.0f;
  253. if(start == 0) {
  254. filter.yn1 = 0.0f;
  255. filter.yn2 = 0.0f;
  256. }
  257. else {
  258. float a = 0.1f * mag; //empirically
  259. float p = RND * 2.0f * PI;
  260. if(start == 1)
  261. a *= RND;
  262. filter.yn1 = a * cosf(p);
  263. filter.yn2 = a * cosf(p + freq * 2.0f * PI / synth->samplerate_f);
  264. //correct the error of computation the start amplitude
  265. //at very high frequencies
  266. if(freq > synth->samplerate_f * 0.96f) {
  267. filter.yn1 = 0.0f;
  268. filter.yn2 = 0.0f;
  269. }
  270. }
  271. filter.amp = amp;
  272. filter.freq = freq;
  273. filter.bw = bw;
  274. computefiltercoefs(filter, freq, bw, 1.0f);
  275. }
  276. /*
  277. * Do the filtering
  278. */
  279. inline void SubFilterA(const float coeff[4], float &src, float work[4])
  280. {
  281. work[3] = src*coeff[0]+work[1]*coeff[1]+work[2]*coeff[2]+work[3]*coeff[3];
  282. work[1] = src;
  283. src = work[3];
  284. }
  285. inline void SubFilterB(const float coeff[4], float &src, float work[4])
  286. {
  287. work[2] = src*coeff[0]+work[0]*coeff[1]+work[3]*coeff[2]+work[2]*coeff[3];
  288. work[0] = src;
  289. src = work[2];
  290. }
  291. //This dance is designed to minimize unneeded memory operations which can result
  292. //in quite a bit of wasted time
  293. void SUBnote::filter(bpfilter &filter, float *smps)
  294. {
  295. assert(synth->buffersize % 8 == 0);
  296. float coeff[4] = {filter.b0, filter.b2, -filter.a1, -filter.a2};
  297. float work[4] = {filter.xn1, filter.xn2, filter.yn1, filter.yn2};
  298. for(int i = 0; i < synth->buffersize; i += 8) {
  299. SubFilterA(coeff, smps[i + 0], work);
  300. SubFilterB(coeff, smps[i + 1], work);
  301. SubFilterA(coeff, smps[i + 2], work);
  302. SubFilterB(coeff, smps[i + 3], work);
  303. SubFilterA(coeff, smps[i + 4], work);
  304. SubFilterB(coeff, smps[i + 5], work);
  305. SubFilterA(coeff, smps[i + 6], work);
  306. SubFilterB(coeff, smps[i + 7], work);
  307. }
  308. filter.xn1 = work[0];
  309. filter.xn2 = work[1];
  310. filter.yn1 = work[2];
  311. filter.yn2 = work[3];
  312. }
  313. /*
  314. * Init Parameters
  315. */
  316. void SUBnote::initparameters(float freq)
  317. {
  318. AmpEnvelope = new Envelope(pars->AmpEnvelope, freq);
  319. if(pars->PFreqEnvelopeEnabled != 0)
  320. FreqEnvelope = new Envelope(pars->FreqEnvelope, freq);
  321. else
  322. FreqEnvelope = NULL;
  323. if(pars->PBandWidthEnvelopeEnabled != 0)
  324. BandWidthEnvelope = new Envelope(pars->BandWidthEnvelope, freq);
  325. else
  326. BandWidthEnvelope = NULL;
  327. if(pars->PGlobalFilterEnabled != 0) {
  328. globalfiltercenterq = pars->GlobalFilter->getq();
  329. GlobalFilterL = Filter::generate(pars->GlobalFilter);
  330. if(stereo)
  331. GlobalFilterR = Filter::generate(pars->GlobalFilter);
  332. GlobalFilterEnvelope = new Envelope(pars->GlobalFilterEnvelope,
  333. freq);
  334. GlobalFilterFreqTracking = pars->GlobalFilter->getfreqtracking(basefreq);
  335. }
  336. computecurrentparameters();
  337. }
  338. /*
  339. * Compute how much to reduce amplitude near nyquist or subaudible frequencies.
  340. */
  341. float SUBnote::computerolloff(float freq)
  342. {
  343. const float lower_limit = 10.0f;
  344. const float lower_width = 10.0f;
  345. const float upper_width = 200.0f;
  346. float upper_limit = synth->samplerate / 2.0f;
  347. if (freq > lower_limit + lower_width &&
  348. freq < upper_limit - upper_width)
  349. return 1.0f;
  350. if (freq <= lower_limit || freq >= upper_limit)
  351. return 0.0f;
  352. if (freq <= lower_limit + lower_width)
  353. return (1.0f - cosf(M_PI * (freq - lower_limit) / lower_width)) / 2.0f;
  354. return (1.0f - cosf(M_PI * (freq - upper_limit) / upper_width)) / 2.0f;
  355. }
  356. /*
  357. * Compute Parameters of SUBnote for each tick
  358. */
  359. void SUBnote::computecurrentparameters()
  360. {
  361. if((FreqEnvelope != NULL) || (BandWidthEnvelope != NULL)
  362. || (oldpitchwheel != ctl->pitchwheel.data)
  363. || (oldbandwidth != ctl->bandwidth.data)
  364. || (portamento != 0)) {
  365. float envfreq = 1.0f;
  366. float envbw = 1.0f;
  367. float gain = 1.0f;
  368. if(FreqEnvelope != NULL) {
  369. envfreq = FreqEnvelope->envout() / 1200;
  370. envfreq = powf(2.0f, envfreq);
  371. }
  372. envfreq *= ctl->pitchwheel.relfreq; //pitch wheel
  373. if(portamento != 0) { //portamento is used
  374. envfreq *= ctl->portamento.freqrap;
  375. if(ctl->portamento.used == 0) //the portamento has finished
  376. portamento = 0; //this note is no longer "portamented"
  377. ;
  378. }
  379. if(BandWidthEnvelope != NULL) {
  380. envbw = BandWidthEnvelope->envout();
  381. envbw = powf(2, envbw);
  382. }
  383. envbw *= ctl->bandwidth.relbw; //bandwidth controller
  384. float tmpgain = 1.0f / sqrt(envbw * envfreq);
  385. for(int n = 0; n < numharmonics; ++n) {
  386. overtone_rolloff[n] = computerolloff(overtone_freq[n] * envfreq);
  387. }
  388. for(int n = 0; n < numharmonics; ++n)
  389. for(int nph = 0; nph < numstages; ++nph) {
  390. if(nph == 0)
  391. gain = tmpgain;
  392. else
  393. gain = 1.0f;
  394. computefiltercoefs(lfilter[nph + n * numstages],
  395. lfilter[nph + n * numstages].freq * envfreq,
  396. lfilter[nph + n * numstages].bw * envbw,
  397. gain);
  398. }
  399. if(stereo != 0)
  400. for(int n = 0; n < numharmonics; ++n)
  401. for(int nph = 0; nph < numstages; ++nph) {
  402. if(nph == 0)
  403. gain = tmpgain;
  404. else
  405. gain = 1.0f;
  406. computefiltercoefs(
  407. rfilter[nph + n * numstages],
  408. rfilter[nph + n
  409. * numstages].freq * envfreq,
  410. rfilter[nph + n * numstages].bw * envbw,
  411. gain);
  412. }
  413. oldbandwidth = ctl->bandwidth.data;
  414. oldpitchwheel = ctl->pitchwheel.data;
  415. }
  416. newamplitude = volume * AmpEnvelope->envout_dB() * 2.0f;
  417. //Filter
  418. if(GlobalFilterL != NULL) {
  419. float globalfilterpitch = GlobalFilterCenterPitch
  420. + GlobalFilterEnvelope->envout();
  421. float filterfreq = globalfilterpitch + ctl->filtercutoff.relfreq
  422. + GlobalFilterFreqTracking;
  423. filterfreq = Filter::getrealfreq(filterfreq);
  424. GlobalFilterL->setfreq_and_q(filterfreq,
  425. globalfiltercenterq * ctl->filterq.relq);
  426. if(GlobalFilterR != NULL)
  427. GlobalFilterR->setfreq_and_q(
  428. filterfreq,
  429. globalfiltercenterq
  430. * ctl->filterq.relq);
  431. }
  432. }
  433. /*
  434. * Note Output
  435. */
  436. int SUBnote::noteout(float *outl, float *outr)
  437. {
  438. memcpy(outl, denormalkillbuf, synth->bufferbytes);
  439. memcpy(outr, denormalkillbuf, synth->bufferbytes);
  440. if(NoteEnabled == OFF)
  441. return 0;
  442. float tmprnd[synth->buffersize];
  443. float tmpsmp[synth->buffersize];
  444. //left channel
  445. for(int i = 0; i < synth->buffersize; ++i)
  446. tmprnd[i] = RND * 2.0f - 1.0f;
  447. for(int n = 0; n < numharmonics; ++n) {
  448. float rolloff = overtone_rolloff[n];
  449. memcpy(tmpsmp, tmprnd, synth->bufferbytes);
  450. for(int nph = 0; nph < numstages; ++nph)
  451. filter(lfilter[nph + n * numstages], tmpsmp);
  452. for(int i = 0; i < synth->buffersize; ++i)
  453. outl[i] += tmpsmp[i] * rolloff;
  454. }
  455. if(GlobalFilterL != NULL)
  456. GlobalFilterL->filterout(&outl[0]);
  457. //right channel
  458. if(stereo != 0) {
  459. for(int i = 0; i < synth->buffersize; ++i)
  460. tmprnd[i] = RND * 2.0f - 1.0f;
  461. for(int n = 0; n < numharmonics; ++n) {
  462. float rolloff = overtone_rolloff[n];
  463. memcpy(tmpsmp, tmprnd, synth->bufferbytes);
  464. for(int nph = 0; nph < numstages; ++nph)
  465. filter(rfilter[nph + n * numstages], tmpsmp);
  466. for(int i = 0; i < synth->buffersize; ++i)
  467. outr[i] += tmpsmp[i] * rolloff;
  468. }
  469. if(GlobalFilterR != NULL)
  470. GlobalFilterR->filterout(&outr[0]);
  471. }
  472. else
  473. memcpy(outr, outl, synth->bufferbytes);
  474. if(firsttick != 0) {
  475. int n = 10;
  476. if(n > synth->buffersize)
  477. n = synth->buffersize;
  478. for(int i = 0; i < n; ++i) {
  479. float ampfadein = 0.5f - 0.5f * cosf(
  480. (float) i / (float) n * PI);
  481. outl[i] *= ampfadein;
  482. outr[i] *= ampfadein;
  483. }
  484. firsttick = 0;
  485. }
  486. if(ABOVE_AMPLITUDE_THRESHOLD(oldamplitude, newamplitude))
  487. // Amplitude interpolation
  488. for(int i = 0; i < synth->buffersize; ++i) {
  489. float tmpvol = INTERPOLATE_AMPLITUDE(oldamplitude,
  490. newamplitude,
  491. i,
  492. synth->buffersize);
  493. outl[i] *= tmpvol * panning;
  494. outr[i] *= tmpvol * (1.0f - panning);
  495. }
  496. else
  497. for(int i = 0; i < synth->buffersize; ++i) {
  498. outl[i] *= newamplitude * panning;
  499. outr[i] *= newamplitude * (1.0f - panning);
  500. }
  501. oldamplitude = newamplitude;
  502. computecurrentparameters();
  503. // Apply legato-specific sound signal modifications
  504. legato.apply(*this, outl, outr);
  505. // Check if the note needs to be computed more
  506. if(AmpEnvelope->finished() != 0) {
  507. for(int i = 0; i < synth->buffersize; ++i) { //fade-out
  508. float tmp = 1.0f - (float)i / synth->buffersize_f;
  509. outl[i] *= tmp;
  510. outr[i] *= tmp;
  511. }
  512. KillNote();
  513. }
  514. return 1;
  515. }
  516. /*
  517. * Relase Key (Note Off)
  518. */
  519. void SUBnote::relasekey()
  520. {
  521. AmpEnvelope->relasekey();
  522. if(FreqEnvelope)
  523. FreqEnvelope->relasekey();
  524. if(BandWidthEnvelope)
  525. BandWidthEnvelope->relasekey();
  526. if(GlobalFilterEnvelope)
  527. GlobalFilterEnvelope->relasekey();
  528. }
  529. /*
  530. * Check if the note is finished
  531. */
  532. int SUBnote::finished() const
  533. {
  534. if(NoteEnabled == OFF)
  535. return 1;
  536. else
  537. return 0;
  538. }