lb302.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. /*
  2. * lb302.cpp - implementation of class lb302 which is a bass synth attempting
  3. * to emulate the Roland TB303 bass synth
  4. *
  5. * Copyright (c) 2006-2008 Paul Giblock <pgib/at/users.sourceforge.net>
  6. *
  7. * This file is part of LMMS - https://lmms.io
  8. *
  9. * lb302FilterIIR2 is based on the gsyn filter code by Andy Sloane.
  10. *
  11. * lb302Filter3Pole is based on the TB303 instrument written by
  12. * Josep M Comajuncosas for the CSounds library
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public
  16. * License as published by the Free Software Foundation; either
  17. * version 2 of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22. * General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public
  25. * License along with this program (see COPYING); if not, write to the
  26. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  27. * Boston, MA 02110-1301 USA.
  28. *
  29. */
  30. // Need to include this first to ensure we get M_PI in MinGW with C++11
  31. #define _USE_MATH_DEFINES
  32. #include <math.h>
  33. #include "lb302.h"
  34. #include "AutomatableButton.h"
  35. #include "Engine.h"
  36. #include "InstrumentPlayHandle.h"
  37. #include "InstrumentTrack.h"
  38. #include "Knob.h"
  39. #include "NotePlayHandle.h"
  40. #include "Oscillator.h"
  41. #include "PixmapButton.h"
  42. #include "ToolTip.h"
  43. #include "BandLimitedWave.h"
  44. #include "embed.h"
  45. #include "plugin_export.h"
  46. // Envelope Recalculation period
  47. #define ENVINC 64
  48. //
  49. // New config
  50. //
  51. #define LB_24_IGNORE_ENVELOPE
  52. #define LB_FILTERED
  53. //#define LB_DECAY
  54. //#define LB_24_RES_TRICK
  55. #define LB_DIST_RATIO 4.0
  56. #define LB_24_VOL_ADJUST 3.0
  57. //#define LB_DECAY_NOTES
  58. #define LB_DEBUG
  59. #ifdef LB_DEBUG
  60. #include <assert.h>
  61. #endif
  62. //
  63. // Old config
  64. //
  65. //#define engine::mixer()->processingSampleRate() 44100.0f
  66. extern "C"
  67. {
  68. Plugin::Descriptor PLUGIN_EXPORT lb302_plugin_descriptor =
  69. {
  70. STRINGIFY( PLUGIN_NAME ),
  71. "LB302",
  72. QT_TRANSLATE_NOOP( "pluginBrowser",
  73. "Incomplete monophonic imitation tb303" ),
  74. "Paul Giblock <pgib/at/users.sf.net>",
  75. 0x0100,
  76. Plugin::Instrument,
  77. new PluginPixmapLoader( "logo" ),
  78. NULL,
  79. NULL
  80. };
  81. }
  82. //
  83. // lb302Filter
  84. //
  85. lb302Filter::lb302Filter(lb302FilterKnobState* p_fs) :
  86. fs(p_fs),
  87. vcf_c0(0),
  88. vcf_e0(0),
  89. vcf_e1(0)
  90. {
  91. };
  92. void lb302Filter::recalc()
  93. {
  94. vcf_e1 = exp(6.109 + 1.5876*(fs->envmod) + 2.1553*(fs->cutoff) - 1.2*(1.0-(fs->reso)));
  95. vcf_e0 = exp(5.613 - 0.8*(fs->envmod) + 2.1553*(fs->cutoff) - 0.7696*(1.0-(fs->reso)));
  96. vcf_e0*=M_PI/Engine::mixer()->processingSampleRate();
  97. vcf_e1*=M_PI/Engine::mixer()->processingSampleRate();
  98. vcf_e1 -= vcf_e0;
  99. vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso));
  100. };
  101. void lb302Filter::envRecalc()
  102. {
  103. vcf_c0 *= fs->envdecay; // Filter Decay. vcf_decay is adjusted for Hz and ENVINC
  104. // vcf_rescoeff = exp(-1.20 + 3.455*(fs->reso)); moved above
  105. };
  106. void lb302Filter::playNote()
  107. {
  108. vcf_c0 = vcf_e1;
  109. }
  110. //
  111. // lb302FilterIIR2
  112. //
  113. lb302FilterIIR2::lb302FilterIIR2(lb302FilterKnobState* p_fs) :
  114. lb302Filter(p_fs),
  115. vcf_d1(0),
  116. vcf_d2(0),
  117. vcf_a(0),
  118. vcf_b(0),
  119. vcf_c(1)
  120. {
  121. m_dist = new DspEffectLibrary::Distortion( 1.0, 1.0f);
  122. };
  123. lb302FilterIIR2::~lb302FilterIIR2()
  124. {
  125. delete m_dist;
  126. }
  127. void lb302FilterIIR2::recalc()
  128. {
  129. lb302Filter::recalc();
  130. //m_dist->setThreshold(0.5+(fs->dist*2.0));
  131. m_dist->setThreshold(fs->dist*75.0);
  132. };
  133. void lb302FilterIIR2::envRecalc()
  134. {
  135. float k, w;
  136. lb302Filter::envRecalc();
  137. w = vcf_e0 + vcf_c0; // e0 is adjusted for Hz and doesn't need ENVINC
  138. k = exp(-w/vcf_rescoeff); // Does this mean c0 is inheritantly?
  139. vcf_a = 2.0*cos(2.0*w) * k;
  140. vcf_b = -k*k;
  141. vcf_c = 1.0 - vcf_a - vcf_b;
  142. }
  143. float lb302FilterIIR2::process(const float& samp)
  144. {
  145. float ret = vcf_a*vcf_d1 + vcf_b*vcf_d2 + vcf_c*samp;
  146. // Delayed samples for filter
  147. vcf_d2 = vcf_d1;
  148. vcf_d1 = ret;
  149. if(fs->dist > 0)
  150. ret=m_dist->nextSample(ret);
  151. // output = IIR2 + dry
  152. return ret;
  153. }
  154. //
  155. // lb302Filter3Pole
  156. //
  157. lb302Filter3Pole::lb302Filter3Pole(lb302FilterKnobState *p_fs) :
  158. lb302Filter(p_fs),
  159. ay1(0),
  160. ay2(0),
  161. aout(0),
  162. lastin(0)
  163. {
  164. };
  165. void lb302Filter3Pole::recalc()
  166. {
  167. // DO NOT CALL BASE CLASS
  168. vcf_e0 = 0.000001;
  169. vcf_e1 = 1.0;
  170. }
  171. // TODO: Try using k instead of vcf_reso
  172. void lb302Filter3Pole::envRecalc()
  173. {
  174. float w,k;
  175. float kfco;
  176. lb302Filter::envRecalc();
  177. // e0 is adjusted for Hz and doesn't need ENVINC
  178. w = vcf_e0 + vcf_c0;
  179. k = (fs->cutoff > 0.975)?0.975:fs->cutoff;
  180. kfco = 50.f + (k)*((2300.f-1600.f*(fs->envmod))+(w) *
  181. (700.f+1500.f*(k)+(1500.f+(k)*(Engine::mixer()->processingSampleRate()/2.f-6000.f)) *
  182. (fs->envmod)) );
  183. //+iacc*(.3+.7*kfco*kenvmod)*kaccent*kaccurve*2000
  184. #ifdef LB_24_IGNORE_ENVELOPE
  185. // kfcn = fs->cutoff;
  186. kfcn = 2.0 * kfco / Engine::mixer()->processingSampleRate();
  187. #else
  188. kfcn = w;
  189. #endif
  190. kp = ((-2.7528*kfcn + 3.0429)*kfcn + 1.718)*kfcn - 0.9984;
  191. kp1 = kp+1.0;
  192. kp1h = 0.5*kp1;
  193. #ifdef LB_24_RES_TRICK
  194. k = exp(-w/vcf_rescoeff);
  195. kres = (((k))) * (((-2.7079*kp1 + 10.963)*kp1 - 14.934)*kp1 + 8.4974);
  196. #else
  197. kres = (((fs->reso))) * (((-2.7079*kp1 + 10.963)*kp1 - 14.934)*kp1 + 8.4974);
  198. #endif
  199. value = 1.0+( (fs->dist) *(1.5 + 2.0*kres*(1.0-kfcn))); // ENVMOD was DIST
  200. }
  201. float lb302Filter3Pole::process(const float& samp)
  202. {
  203. float ax1 = lastin;
  204. float ay11 = ay1;
  205. float ay31 = ay2;
  206. lastin = (samp) - tanh(kres*aout);
  207. ay1 = kp1h * (lastin+ax1) - kp*ay1;
  208. ay2 = kp1h * (ay1 + ay11) - kp*ay2;
  209. aout = kp1h * (ay2 + ay31) - kp*aout;
  210. return tanh(aout*value)*LB_24_VOL_ADJUST/(1.0+fs->dist);
  211. }
  212. //
  213. // LBSynth
  214. //
  215. lb302Synth::lb302Synth( InstrumentTrack * _instrumentTrack ) :
  216. Instrument( _instrumentTrack, &lb302_plugin_descriptor ),
  217. vcf_cut_knob( 0.75f, 0.0f, 1.5f, 0.005f, this, tr( "VCF Cutoff Frequency" ) ),
  218. vcf_res_knob( 0.75f, 0.0f, 1.25f, 0.005f, this, tr( "VCF Resonance" ) ),
  219. vcf_mod_knob( 0.1f, 0.0f, 1.0f, 0.005f, this, tr( "VCF Envelope Mod" ) ),
  220. vcf_dec_knob( 0.1f, 0.0f, 1.0f, 0.005f, this, tr( "VCF Envelope Decay" ) ),
  221. dist_knob( 0.0f, 0.0f, 1.0f, 0.01f, this, tr( "Distortion" ) ),
  222. wave_shape( 8.0f, 0.0f, 11.0f, this, tr( "Waveform" ) ),
  223. slide_dec_knob( 0.6f, 0.0f, 1.0f, 0.005f, this, tr( "Slide Decay" ) ),
  224. slideToggle( false, this, tr( "Slide" ) ),
  225. accentToggle( false, this, tr( "Accent" ) ),
  226. deadToggle( false, this, tr( "Dead" ) ),
  227. db24Toggle( false, this, tr( "24dB/oct Filter" ) ),
  228. vca_attack(1.0 - 0.96406088),
  229. vca_decay(0.99897516),
  230. vca_a0(0.5),
  231. vca_a(0.),
  232. vca_mode(never_played)
  233. {
  234. connect( Engine::mixer(), SIGNAL( sampleRateChanged( ) ),
  235. this, SLOT ( filterChanged( ) ) );
  236. connect( &vcf_cut_knob, SIGNAL( dataChanged( ) ),
  237. this, SLOT ( filterChanged( ) ) );
  238. connect( &vcf_res_knob, SIGNAL( dataChanged( ) ),
  239. this, SLOT ( filterChanged( ) ) );
  240. connect( &vcf_mod_knob, SIGNAL( dataChanged( ) ),
  241. this, SLOT ( filterChanged( ) ) );
  242. connect( &vcf_dec_knob, SIGNAL( dataChanged( ) ),
  243. this, SLOT ( filterChanged( ) ) );
  244. connect( &db24Toggle, SIGNAL( dataChanged( ) ),
  245. this, SLOT ( db24Toggled( ) ) );
  246. connect( &dist_knob, SIGNAL( dataChanged( ) ),
  247. this, SLOT ( filterChanged( )));
  248. // SYNTH
  249. vco_inc = 0.0;
  250. vco_c = 0;
  251. vco_k = 0;
  252. vco_slide = 0; vco_slideinc = 0;
  253. vco_slidebase = 0;
  254. fs.cutoff = 0;
  255. fs.envmod = 0;
  256. fs.reso = 0;
  257. fs.envdecay = 0;
  258. fs.dist = 0;
  259. vcf_envpos = ENVINC;
  260. vco_shape = BL_SAWTOOTH;
  261. vcfs[0] = new lb302FilterIIR2(&fs);
  262. vcfs[1] = new lb302Filter3Pole(&fs);
  263. db24Toggled();
  264. sample_cnt = 0;
  265. release_frame = 0;
  266. catch_frame = 0;
  267. catch_decay = 0;
  268. last_offset = 0;
  269. new_freq = false;
  270. filterChanged();
  271. InstrumentPlayHandle * iph = new InstrumentPlayHandle( this, _instrumentTrack );
  272. Engine::mixer()->addPlayHandle( iph );
  273. }
  274. lb302Synth::~lb302Synth()
  275. {
  276. for (int i=0; i<NUM_FILTERS; ++i) {
  277. delete vcfs[i];
  278. }
  279. }
  280. void lb302Synth::saveSettings( QDomDocument & _doc,
  281. QDomElement & _this )
  282. {
  283. vcf_cut_knob.saveSettings( _doc, _this, "vcf_cut" );
  284. vcf_res_knob.saveSettings( _doc, _this, "vcf_res" );
  285. vcf_mod_knob.saveSettings( _doc, _this, "vcf_mod" );
  286. vcf_dec_knob.saveSettings( _doc, _this, "vcf_dec" );
  287. wave_shape.saveSettings( _doc, _this, "shape");
  288. dist_knob.saveSettings( _doc, _this, "dist");
  289. slide_dec_knob.saveSettings( _doc, _this, "slide_dec");
  290. slideToggle.saveSettings( _doc, _this, "slide");
  291. deadToggle.saveSettings( _doc, _this, "dead");
  292. db24Toggle.saveSettings( _doc, _this, "db24");
  293. }
  294. void lb302Synth::loadSettings( const QDomElement & _this )
  295. {
  296. vcf_cut_knob.loadSettings( _this, "vcf_cut" );
  297. vcf_res_knob.loadSettings( _this, "vcf_res" );
  298. vcf_mod_knob.loadSettings( _this, "vcf_mod" );
  299. vcf_dec_knob.loadSettings( _this, "vcf_dec" );
  300. dist_knob.loadSettings( _this, "dist");
  301. slide_dec_knob.loadSettings( _this, "slide_dec");
  302. wave_shape.loadSettings( _this, "shape");
  303. slideToggle.loadSettings( _this, "slide");
  304. deadToggle.loadSettings( _this, "dead");
  305. db24Toggle.loadSettings( _this, "db24");
  306. db24Toggled();
  307. filterChanged();
  308. }
  309. // TODO: Split into one function per knob. envdecay doesn't require
  310. // recalcFilter.
  311. void lb302Synth::filterChanged()
  312. {
  313. fs.cutoff = vcf_cut_knob.value();
  314. fs.reso = vcf_res_knob.value();
  315. fs.envmod = vcf_mod_knob.value();
  316. fs.dist = LB_DIST_RATIO*dist_knob.value();
  317. float d = 0.2 + (2.3*vcf_dec_knob.value());
  318. d *= Engine::mixer()->processingSampleRate(); // d *= smpl rate
  319. fs.envdecay = pow(0.1, 1.0/d * ENVINC); // decay is 0.1 to the 1/d * ENVINC
  320. // vcf_envdecay is now adjusted for both
  321. // sampling rate and ENVINC
  322. recalcFilter();
  323. }
  324. void lb302Synth::db24Toggled()
  325. {
  326. vcf = vcfs[db24Toggle.value()];
  327. // These recalcFilter calls might suck
  328. recalcFilter();
  329. }
  330. QString lb302Synth::nodeName() const
  331. {
  332. return( lb302_plugin_descriptor.name );
  333. }
  334. // OBSOLETE. Break apart once we get Q_OBJECT to work. >:[
  335. void lb302Synth::recalcFilter()
  336. {
  337. vcf.load()->recalc();
  338. // THIS IS OLD 3pole/24dB code, I may reintegrate it. Don't need it
  339. // right now. Should be toggled by LB_24_RES_TRICK at the moment.
  340. /*kfcn = 2.0 * (((vcf_cutoff*3000))) / engine::mixer()->processingSampleRate();
  341. kp = ((-2.7528*kfcn + 3.0429)*kfcn + 1.718)*kfcn - 0.9984;
  342. kp1 = kp+1.0;
  343. kp1h = 0.5*kp1;
  344. kres = (((vcf_reso))) * (((-2.7079*kp1 + 10.963)*kp1 - 14.934)*kp1 + 8.4974);
  345. value = 1.0+( (((0))) *(1.5 + 2.0*kres*(1.0-kfcn))); // ENVMOD was DIST*/
  346. vcf_envpos = ENVINC; // Trigger filter update in process()
  347. }
  348. inline float GET_INC(float freq) {
  349. return freq/Engine::mixer()->processingSampleRate(); // TODO: Use actual sampling rate.
  350. }
  351. int lb302Synth::process(sampleFrame *outbuf, const int size)
  352. {
  353. const float sampleRatio = 44100.f / Engine::mixer()->processingSampleRate();
  354. float w;
  355. float samp;
  356. // Hold on to the current VCF, and use it throughout this period
  357. lb302Filter *filter = vcf.loadAcquire();
  358. if( release_frame == 0 || ! m_playingNote )
  359. {
  360. vca_mode = decay;
  361. }
  362. if( new_freq )
  363. {
  364. //printf(" playing new note..\n");
  365. lb302Note note;
  366. note.vco_inc = GET_INC( true_freq );
  367. note.dead = deadToggle.value();
  368. initNote(&note);
  369. new_freq = false;
  370. }
  371. // TODO: NORMAL RELEASE
  372. // vca_mode = 1;
  373. for( int i=0; i<size; i++ )
  374. {
  375. // start decay if we're past release
  376. if( i >= release_frame )
  377. {
  378. vca_mode = decay;
  379. }
  380. // update vcf
  381. if(vcf_envpos >= ENVINC) {
  382. filter->envRecalc();
  383. vcf_envpos = 0;
  384. if (vco_slide) {
  385. vco_inc = vco_slidebase - vco_slide;
  386. // Calculate coeff from dec_knob on knob change.
  387. vco_slide -= vco_slide * ( 0.1f - slide_dec_knob.value() * 0.0999f ) * sampleRatio; // TODO: Adjust for ENVINC
  388. }
  389. }
  390. sample_cnt++;
  391. vcf_envpos++;
  392. //int decay_frames = 128;
  393. // update vco
  394. vco_c += vco_inc;
  395. if(vco_c > 0.5)
  396. vco_c -= 1.0;
  397. switch(int(rint(wave_shape.value()))) {
  398. case 0: vco_shape = SAWTOOTH; break;
  399. case 1: vco_shape = TRIANGLE; break;
  400. case 2: vco_shape = SQUARE; break;
  401. case 3: vco_shape = ROUND_SQUARE; break;
  402. case 4: vco_shape = MOOG; break;
  403. case 5: vco_shape = SINE; break;
  404. case 6: vco_shape = EXPONENTIAL; break;
  405. case 7: vco_shape = WHITE_NOISE; break;
  406. case 8: vco_shape = BL_SAWTOOTH; break;
  407. case 9: vco_shape = BL_SQUARE; break;
  408. case 10: vco_shape = BL_TRIANGLE; break;
  409. case 11: vco_shape = BL_MOOG; break;
  410. default: vco_shape = SAWTOOTH; break;
  411. }
  412. // add vco_shape_param the changes the shape of each curve.
  413. // merge sawtooths with triangle and square with round square?
  414. switch (vco_shape) {
  415. case SAWTOOTH: // p0: curviness of line
  416. vco_k = vco_c; // Is this sawtooth backwards?
  417. break;
  418. case TRIANGLE: // p0: duty rev.saw<->triangle<->saw p1: curviness
  419. vco_k = (vco_c*2.0)+0.5;
  420. if (vco_k>0.5)
  421. vco_k = 1.0- vco_k;
  422. break;
  423. case SQUARE: // p0: slope of top
  424. vco_k = (vco_c<0)?0.5:-0.5;
  425. break;
  426. case ROUND_SQUARE: // p0: width of round
  427. vco_k = (vco_c<0)?(sqrtf(1-(vco_c*vco_c*4))-0.5):-0.5;
  428. break;
  429. case MOOG: // Maybe the fall should be exponential/sinsoidal instead of quadric.
  430. // [-0.5, 0]: Rise, [0,0.25]: Slope down, [0.25,0.5]: Low
  431. vco_k = (vco_c*2.0)+0.5;
  432. if (vco_k>1.0) {
  433. vco_k = -0.5 ;
  434. }
  435. else if (vco_k>0.5) {
  436. w = 2.0*(vco_k-0.5)-1.0;
  437. vco_k = 0.5 - sqrtf(1.0-(w*w));
  438. }
  439. vco_k *= 2.0; // MOOG wave gets filtered away
  440. break;
  441. case SINE:
  442. // [-0.5, 0.5] : [-pi, pi]
  443. vco_k = 0.5f * Oscillator::sinSample( vco_c );
  444. break;
  445. case EXPONENTIAL:
  446. vco_k = 0.5 * Oscillator::expSample( vco_c );
  447. break;
  448. case WHITE_NOISE:
  449. vco_k = 0.5 * Oscillator::noiseSample( vco_c );
  450. break;
  451. case BL_SAWTOOTH:
  452. vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSaw ) * 0.5f;
  453. break;
  454. case BL_SQUARE:
  455. vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLSquare ) * 0.5f;
  456. break;
  457. case BL_TRIANGLE:
  458. vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLTriangle ) * 0.5f;
  459. break;
  460. case BL_MOOG:
  461. vco_k = BandLimitedWave::oscillate( vco_c + 0.5f, BandLimitedWave::pdToLen( vco_inc ), BandLimitedWave::BLMoog );
  462. break;
  463. }
  464. //vca_a = 0.5;
  465. // Write out samples.
  466. #ifdef LB_FILTERED
  467. //samp = vcf->process(vco_k)*2.0*vca_a;
  468. //samp = vcf->process(vco_k)*2.0;
  469. samp = filter->process(vco_k) * vca_a;
  470. //printf("%f %d\n", vco_c, sample_cnt);
  471. //samp = vco_k * vca_a;
  472. if( sample_cnt <= 4 )
  473. {
  474. // vca_a = 0;
  475. }
  476. #else
  477. //samp = vco_k*vca_a;
  478. #endif
  479. /*
  480. float releaseFrames = desiredReleaseFrames();
  481. samp *= (releaseFrames - catch_decay)/releaseFrames;
  482. */
  483. //LB302 samp *= (float)(decay_frames - catch_decay)/(float)decay_frames;
  484. for( int c = 0; c < DEFAULT_CHANNELS; c++ )
  485. {
  486. outbuf[i][c] = samp;
  487. }
  488. // Handle Envelope
  489. if(vca_mode==attack) {
  490. vca_a+=(vca_a0-vca_a)*vca_attack;
  491. if(sample_cnt>=0.5*Engine::mixer()->processingSampleRate())
  492. vca_mode = idle;
  493. }
  494. else if(vca_mode == decay) {
  495. vca_a *= vca_decay;
  496. // the following line actually speeds up processing
  497. if(vca_a < (1/65536.0)) {
  498. vca_a = 0;
  499. vca_mode = never_played;
  500. }
  501. }
  502. }
  503. return 1;
  504. }
  505. /* Prepares the active LB302 note. I separated this into a function because it
  506. * needs to be called onplayNote() when a new note is started. It also needs
  507. * to be called from process() when a prior edge-to-edge note is done releasing.
  508. */
  509. void lb302Synth::initNote( lb302Note *n)
  510. {
  511. catch_decay = 0;
  512. vco_inc = n->vco_inc;
  513. // Always reset vca on non-dead notes, and
  514. // Only reset vca on decaying(decayed) and never-played
  515. if(n->dead == 0 || (vca_mode == decay || vca_mode == never_played)) {
  516. //printf(" good\n");
  517. sample_cnt = 0;
  518. vca_mode = attack;
  519. // LB303:
  520. //vca_a = 0;
  521. }
  522. else {
  523. vca_mode = idle;
  524. }
  525. initSlide();
  526. // Slide-from note, save inc for next note
  527. if (slideToggle.value()) {
  528. vco_slideinc = vco_inc; // May need to equal vco_slidebase+vco_slide if last note slid
  529. }
  530. recalcFilter();
  531. if(n->dead ==0){
  532. // Swap next two blocks??
  533. vcf.load()->playNote();
  534. // Ensure envelope is recalculated
  535. vcf_envpos = ENVINC;
  536. // Double Check
  537. //vca_mode = 0;
  538. //vca_a = 0.0;
  539. }
  540. }
  541. void lb302Synth::initSlide()
  542. {
  543. // Initiate Slide
  544. if (vco_slideinc) {
  545. //printf(" sliding\n");
  546. vco_slide = vco_inc-vco_slideinc; // Slide amount
  547. vco_slidebase = vco_inc; // The REAL frequency
  548. vco_slideinc = 0; // reset from-note
  549. }
  550. else {
  551. vco_slide = 0;
  552. }
  553. }
  554. void lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer )
  555. {
  556. if( _n->isMasterNote() || ( _n->hasParent() && _n->isReleased() ) )
  557. {
  558. return;
  559. }
  560. // sort notes: new notes to the end
  561. m_notesMutex.lock();
  562. if( _n->totalFramesPlayed() == 0 )
  563. {
  564. m_notes.append( _n );
  565. }
  566. else
  567. {
  568. m_notes.prepend( _n );
  569. }
  570. m_notesMutex.unlock();
  571. release_frame = qMax( release_frame, _n->framesLeft() + _n->offset() );
  572. }
  573. void lb302Synth::processNote( NotePlayHandle * _n )
  574. {
  575. /// Start a new note.
  576. if( _n->m_pluginData != this )
  577. {
  578. m_playingNote = _n;
  579. new_freq = true;
  580. _n->m_pluginData = this;
  581. }
  582. if( ! m_playingNote && ! _n->isReleased() && release_frame > 0 )
  583. {
  584. m_playingNote = _n;
  585. if ( slideToggle.value() )
  586. {
  587. vco_slideinc = GET_INC( _n->frequency() );
  588. }
  589. }
  590. // Check for slide
  591. if( m_playingNote == _n )
  592. {
  593. true_freq = _n->frequency();
  594. if( slideToggle.value() ) {
  595. vco_slidebase = GET_INC( true_freq ); // The REAL frequency
  596. }
  597. else {
  598. vco_inc = GET_INC( true_freq );
  599. }
  600. }
  601. }
  602. void lb302Synth::play( sampleFrame * _working_buffer )
  603. {
  604. m_notesMutex.lock();
  605. while( ! m_notes.isEmpty() )
  606. {
  607. processNote( m_notes.takeFirst() );
  608. };
  609. m_notesMutex.unlock();
  610. const fpp_t frames = Engine::mixer()->framesPerPeriod();
  611. process( _working_buffer, frames );
  612. instrumentTrack()->processAudioBuffer( _working_buffer, frames, NULL );
  613. // release_frame = 0; //removed for issue # 1432
  614. }
  615. void lb302Synth::deleteNotePluginData( NotePlayHandle * _n )
  616. {
  617. //printf("GONE\n");
  618. if( m_playingNote == _n )
  619. {
  620. m_playingNote = NULL;
  621. }
  622. }
  623. PluginView * lb302Synth::instantiateView( QWidget * _parent )
  624. {
  625. return( new lb302SynthView( this, _parent ) );
  626. }
  627. lb302SynthView::lb302SynthView( Instrument * _instrument, QWidget * _parent ) :
  628. InstrumentViewFixedSize( _instrument, _parent )
  629. {
  630. // GUI
  631. m_vcfCutKnob = new Knob( knobBright_26, this );
  632. m_vcfCutKnob->move( 75, 130 );
  633. m_vcfCutKnob->setHintText( tr( "Cutoff Freq:" ), "" );
  634. m_vcfCutKnob->setLabel( "" );
  635. m_vcfResKnob = new Knob( knobBright_26, this );
  636. m_vcfResKnob->move( 120, 130 );
  637. m_vcfResKnob->setHintText( tr( "Resonance:" ), "" );
  638. m_vcfResKnob->setLabel( "" );
  639. m_vcfModKnob = new Knob( knobBright_26, this );
  640. m_vcfModKnob->move( 165, 130 );
  641. m_vcfModKnob->setHintText( tr( "Env Mod:" ), "" );
  642. m_vcfModKnob->setLabel( "" );
  643. m_vcfDecKnob = new Knob( knobBright_26, this );
  644. m_vcfDecKnob->move( 210, 130 );
  645. m_vcfDecKnob->setHintText( tr( "Decay:" ), "" );
  646. m_vcfDecKnob->setLabel( "" );
  647. m_slideToggle = new LedCheckBox( "", this );
  648. m_slideToggle->move( 10, 180 );
  649. /* m_accentToggle = new LedCheckBox( "", this );
  650. m_accentToggle->move( 10, 200 );
  651. m_accentToggle->setDisabled(true);*/ // accent removed pending real implementation - no need for non-functional buttons
  652. m_deadToggle = new LedCheckBox( "", this );
  653. m_deadToggle->move( 10, 200 );
  654. m_db24Toggle = new LedCheckBox( "", this );
  655. m_db24Toggle->move( 10, 150);
  656. ToolTip::add( m_db24Toggle,
  657. tr( "303-es-que, 24dB/octave, 3 pole filter" ) );
  658. m_slideDecKnob = new Knob( knobBright_26, this );
  659. m_slideDecKnob->move( 210, 75 );
  660. m_slideDecKnob->setHintText( tr( "Slide Decay:" ), "" );
  661. m_slideDecKnob->setLabel( "");
  662. m_distKnob = new Knob( knobBright_26, this );
  663. m_distKnob->move( 210, 190 );
  664. m_distKnob->setHintText( tr( "DIST:" ), "" );
  665. m_distKnob->setLabel( tr( ""));
  666. // Shapes
  667. // move to 120,75
  668. const int waveBtnX = 10;
  669. const int waveBtnY = 96;
  670. PixmapButton * sawWaveBtn = new PixmapButton( this, tr( "Saw wave" ) );
  671. sawWaveBtn->move( waveBtnX, waveBtnY );
  672. sawWaveBtn->setActiveGraphic( embed::getIconPixmap(
  673. "saw_wave_active" ) );
  674. sawWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  675. "saw_wave_inactive" ) );
  676. ToolTip::add( sawWaveBtn,
  677. tr( "Click here for a saw-wave." ) );
  678. PixmapButton * triangleWaveBtn =
  679. new PixmapButton( this, tr( "Triangle wave" ) );
  680. triangleWaveBtn->move( waveBtnX+(16*1), waveBtnY );
  681. triangleWaveBtn->setActiveGraphic(
  682. embed::getIconPixmap( "triangle_wave_active" ) );
  683. triangleWaveBtn->setInactiveGraphic(
  684. embed::getIconPixmap( "triangle_wave_inactive" ) );
  685. ToolTip::add( triangleWaveBtn,
  686. tr( "Click here for a triangle-wave." ) );
  687. PixmapButton * sqrWaveBtn = new PixmapButton( this, tr( "Square wave" ) );
  688. sqrWaveBtn->move( waveBtnX+(16*2), waveBtnY );
  689. sqrWaveBtn->setActiveGraphic( embed::getIconPixmap(
  690. "square_wave_active" ) );
  691. sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  692. "square_wave_inactive" ) );
  693. ToolTip::add( sqrWaveBtn,
  694. tr( "Click here for a square-wave." ) );
  695. PixmapButton * roundSqrWaveBtn =
  696. new PixmapButton( this, tr( "Rounded square wave" ) );
  697. roundSqrWaveBtn->move( waveBtnX+(16*3), waveBtnY );
  698. roundSqrWaveBtn->setActiveGraphic( embed::getIconPixmap(
  699. "round_square_wave_active" ) );
  700. roundSqrWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  701. "round_square_wave_inactive" ) );
  702. ToolTip::add( roundSqrWaveBtn,
  703. tr( "Click here for a square-wave with a rounded end." ) );
  704. PixmapButton * moogWaveBtn =
  705. new PixmapButton( this, tr( "Moog wave" ) );
  706. moogWaveBtn->move( waveBtnX+(16*4), waveBtnY );
  707. moogWaveBtn->setActiveGraphic(
  708. embed::getIconPixmap( "moog_saw_wave_active" ) );
  709. moogWaveBtn->setInactiveGraphic(
  710. embed::getIconPixmap( "moog_saw_wave_inactive" ) );
  711. ToolTip::add( moogWaveBtn,
  712. tr( "Click here for a moog-like wave." ) );
  713. PixmapButton * sinWaveBtn = new PixmapButton( this, tr( "Sine wave" ) );
  714. sinWaveBtn->move( waveBtnX+(16*5), waveBtnY );
  715. sinWaveBtn->setActiveGraphic( embed::getIconPixmap(
  716. "sin_wave_active" ) );
  717. sinWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  718. "sin_wave_inactive" ) );
  719. ToolTip::add( sinWaveBtn,
  720. tr( "Click for a sine-wave." ) );
  721. PixmapButton * exponentialWaveBtn =
  722. new PixmapButton( this, tr( "White noise wave" ) );
  723. exponentialWaveBtn->move( waveBtnX+(16*6), waveBtnY );
  724. exponentialWaveBtn->setActiveGraphic(
  725. embed::getIconPixmap( "exp_wave_active" ) );
  726. exponentialWaveBtn->setInactiveGraphic(
  727. embed::getIconPixmap( "exp_wave_inactive" ) );
  728. ToolTip::add( exponentialWaveBtn,
  729. tr( "Click here for an exponential wave." ) );
  730. PixmapButton * whiteNoiseWaveBtn =
  731. new PixmapButton( this, tr( "White noise wave" ) );
  732. whiteNoiseWaveBtn->move( waveBtnX+(16*7), waveBtnY );
  733. whiteNoiseWaveBtn->setActiveGraphic(
  734. embed::getIconPixmap( "white_noise_wave_active" ) );
  735. whiteNoiseWaveBtn->setInactiveGraphic(
  736. embed::getIconPixmap( "white_noise_wave_inactive" ) );
  737. ToolTip::add( whiteNoiseWaveBtn,
  738. tr( "Click here for white-noise." ) );
  739. PixmapButton * blSawWaveBtn =
  740. new PixmapButton( this, tr( "Bandlimited saw wave" ) );
  741. blSawWaveBtn->move( waveBtnX+(16*9)-8, waveBtnY );
  742. blSawWaveBtn->setActiveGraphic(
  743. embed::getIconPixmap( "saw_wave_active" ) );
  744. blSawWaveBtn->setInactiveGraphic(
  745. embed::getIconPixmap( "saw_wave_inactive" ) );
  746. ToolTip::add( blSawWaveBtn,
  747. tr( "Click here for bandlimited saw wave." ) );
  748. PixmapButton * blSquareWaveBtn =
  749. new PixmapButton( this, tr( "Bandlimited square wave" ) );
  750. blSquareWaveBtn->move( waveBtnX+(16*10)-8, waveBtnY );
  751. blSquareWaveBtn->setActiveGraphic(
  752. embed::getIconPixmap( "square_wave_active" ) );
  753. blSquareWaveBtn->setInactiveGraphic(
  754. embed::getIconPixmap( "square_wave_inactive" ) );
  755. ToolTip::add( blSquareWaveBtn,
  756. tr( "Click here for bandlimited square wave." ) );
  757. PixmapButton * blTriangleWaveBtn =
  758. new PixmapButton( this, tr( "Bandlimited triangle wave" ) );
  759. blTriangleWaveBtn->move( waveBtnX+(16*11)-8, waveBtnY );
  760. blTriangleWaveBtn->setActiveGraphic(
  761. embed::getIconPixmap( "triangle_wave_active" ) );
  762. blTriangleWaveBtn->setInactiveGraphic(
  763. embed::getIconPixmap( "triangle_wave_inactive" ) );
  764. ToolTip::add( blTriangleWaveBtn,
  765. tr( "Click here for bandlimited triangle wave." ) );
  766. PixmapButton * blMoogWaveBtn =
  767. new PixmapButton( this, tr( "Bandlimited moog saw wave" ) );
  768. blMoogWaveBtn->move( waveBtnX+(16*12)-8, waveBtnY );
  769. blMoogWaveBtn->setActiveGraphic(
  770. embed::getIconPixmap( "moog_saw_wave_active" ) );
  771. blMoogWaveBtn->setInactiveGraphic(
  772. embed::getIconPixmap( "moog_saw_wave_inactive" ) );
  773. ToolTip::add( blMoogWaveBtn,
  774. tr( "Click here for bandlimited moog saw wave." ) );
  775. m_waveBtnGrp = new automatableButtonGroup( this );
  776. m_waveBtnGrp->addButton( sawWaveBtn );
  777. m_waveBtnGrp->addButton( triangleWaveBtn );
  778. m_waveBtnGrp->addButton( sqrWaveBtn );
  779. m_waveBtnGrp->addButton( roundSqrWaveBtn );
  780. m_waveBtnGrp->addButton( moogWaveBtn );
  781. m_waveBtnGrp->addButton( sinWaveBtn );
  782. m_waveBtnGrp->addButton( exponentialWaveBtn );
  783. m_waveBtnGrp->addButton( whiteNoiseWaveBtn );
  784. m_waveBtnGrp->addButton( blSawWaveBtn );
  785. m_waveBtnGrp->addButton( blSquareWaveBtn );
  786. m_waveBtnGrp->addButton( blTriangleWaveBtn );
  787. m_waveBtnGrp->addButton( blMoogWaveBtn );
  788. setAutoFillBackground( true );
  789. QPalette pal;
  790. pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(
  791. "artwork" ) );
  792. setPalette( pal );
  793. }
  794. lb302SynthView::~lb302SynthView()
  795. {
  796. }
  797. void lb302SynthView::modelChanged()
  798. {
  799. lb302Synth * syn = castModel<lb302Synth>();
  800. m_vcfCutKnob->setModel( &syn->vcf_cut_knob );
  801. m_vcfResKnob->setModel( &syn->vcf_res_knob );
  802. m_vcfDecKnob->setModel( &syn->vcf_dec_knob );
  803. m_vcfModKnob->setModel( &syn->vcf_mod_knob );
  804. m_slideDecKnob->setModel( &syn->slide_dec_knob );
  805. m_distKnob->setModel( &syn->dist_knob );
  806. m_waveBtnGrp->setModel( &syn->wave_shape );
  807. m_slideToggle->setModel( &syn->slideToggle );
  808. /*m_accentToggle->setModel( &syn->accentToggle );*/
  809. m_deadToggle->setModel( &syn->deadToggle );
  810. m_db24Toggle->setModel( &syn->db24Toggle );
  811. }
  812. extern "C"
  813. {
  814. // necessary for getting instance out of shared lib
  815. PLUGIN_EXPORT Plugin * lmms_plugin_main( Model * m, void * )
  816. {
  817. return( new lb302Synth(
  818. static_cast<InstrumentTrack *>( m ) ) );
  819. }
  820. }