Monstro.cpp 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979
  1. /*
  2. * Monstro.cpp - a monstrous semi-modular 3-osc synth with modulation matrix
  3. *
  4. * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
  5. *
  6. * This file is part of LMMS - https://lmms.io
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public
  19. * License along with this program (see COPYING); if not, write to the
  20. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301 USA.
  22. *
  23. */
  24. #include <QDomElement>
  25. #include "Monstro.h"
  26. #include "Engine.h"
  27. #include "InstrumentTrack.h"
  28. #include "templates.h"
  29. #include "gui_templates.h"
  30. #include "ToolTip.h"
  31. #include "Song.h"
  32. #include "lmms_math.h"
  33. #include "interpolation.h"
  34. #include "embed.cpp"
  35. extern "C"
  36. {
  37. Plugin::Descriptor PLUGIN_EXPORT monstro_plugin_descriptor =
  38. {
  39. STRINGIFY( PLUGIN_NAME ),
  40. "Monstro",
  41. QT_TRANSLATE_NOOP( "pluginBrowser",
  42. "Monstrous 3-oscillator synth with modulation matrix" ),
  43. "Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
  44. 0x0100,
  45. Plugin::Instrument,
  46. new PluginPixmapLoader( "logo" ),
  47. NULL,
  48. NULL
  49. } ;
  50. }
  51. MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph ) :
  52. m_parent( _i ),
  53. m_nph( _nph )
  54. {
  55. m_osc1l_phase = 0.0f;
  56. m_osc1r_phase = 0.0f;
  57. m_osc2l_phase = 0.0f;
  58. m_osc2r_phase = 0.0f;
  59. m_osc3l_phase = 0.0f;
  60. m_osc3r_phase = 0.0f;
  61. m_ph2l_last = 0.0f;
  62. m_ph2r_last = 0.0f;
  63. m_ph3l_last = 0.0f;
  64. m_ph3r_last = 0.0f;
  65. m_env_phase[0] = 0.0f;
  66. m_env_phase[1] = 0.0f;
  67. m_lfo_phase[0] = 0.0f;
  68. m_lfo_phase[1] = 0.0f;
  69. m_lfo_next[0] = Oscillator::noiseSample( 0.0f );
  70. m_lfo_next[1] = Oscillator::noiseSample( 0.0f );
  71. m_osc1l_last = 0.0f;
  72. m_osc1r_last = 0.0f;
  73. m_l_last = 0.0f;
  74. m_r_last = 0.0f;
  75. m_invert2l = false;
  76. m_invert2r = false;
  77. m_invert3l = false;
  78. m_invert3r = false;
  79. m_counter2l = 0;
  80. m_counter2r = 0;
  81. m_counter3l = 0;
  82. m_counter3r = 0;
  83. }
  84. MonstroSynth::~MonstroSynth()
  85. {
  86. }
  87. void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
  88. {
  89. float modtmp; // temp variable for freq modulation
  90. // macros for modulating with env/lfos
  91. #define modulatefreq( car, mod ) \
  92. modtmp = 0.0f; \
  93. if( mod##_e1 != 0.0f ) modtmp += env[0][f] * mod##_e1; \
  94. if( mod##_e2 != 0.0f ) modtmp += env[1][f] * mod##_e2; \
  95. if( mod##_l1 != 0.0f ) modtmp += lfo[0][f] * mod##_l1; \
  96. if( mod##_l2 != 0.0f ) modtmp += lfo[1][f] * mod##_l2; \
  97. car = qBound( MIN_FREQ, car * powf( 2.0f, modtmp ), MAX_FREQ );
  98. #define modulateabs( car, mod ) \
  99. if( mod##_e1 != 0.0f ) car += env[0][f] * mod##_e1; \
  100. if( mod##_e2 != 0.0f ) car += env[1][f] * mod##_e2; \
  101. if( mod##_l1 != 0.0f ) car += lfo[0][f] * mod##_l1; \
  102. if( mod##_l2 != 0.0f ) car += lfo[1][f] * mod##_l2;
  103. #define modulatephs( car, mod ) \
  104. if( mod##_e1 != 0.0f ) car += env[0][f] * mod##_e1; \
  105. if( mod##_e2 != 0.0f ) car += env[1][f] * mod##_e2; \
  106. if( mod##_l1 != 0.0f ) car += lfo[0][f] * mod##_l1; \
  107. if( mod##_l2 != 0.0f ) car += lfo[1][f] * mod##_l2;
  108. #define modulatevol( car, mod ) \
  109. if( mod##_e1 > 0.0f ) car *= ( 1.0f - mod##_e1 + mod##_e1 * env[0][f] ); \
  110. if( mod##_e1 < 0.0f ) car *= ( 1.0f + mod##_e1 * env[0][f] ); \
  111. if( mod##_e2 > 0.0f ) car *= ( 1.0f - mod##_e2 + mod##_e2 * env[1][f] ); \
  112. if( mod##_e2 < 0.0f ) car *= ( 1.0f + mod##_e2 * env[1][f] ); \
  113. if( mod##_l1 != 0.0f ) car *= ( 1.0f + mod##_l1 * lfo[0][f] ); \
  114. if( mod##_l2 != 0.0f ) car *= ( 1.0f + mod##_l2 * lfo[1][f] ); \
  115. car = qBound( -MODCLIP, car, MODCLIP );
  116. ////////////////////
  117. // //
  118. // MODULATORS //
  119. // //
  120. ////////////////////
  121. // LFO phase offsets
  122. const float lfo1_po = m_parent->m_lfo1Phs.value() / 360.0f;
  123. const float lfo2_po = m_parent->m_lfo2Phs.value() / 360.0f;
  124. // remove cruft from phase counters to prevent overflow, add phase offset
  125. m_lfo_phase[0] = absFraction( m_lfo_phase[0] + lfo1_po );
  126. m_lfo_phase[1] = absFraction( m_lfo_phase[1] + lfo2_po );
  127. // LFO rates and increment
  128. m_lfo_rate[0] = ( m_parent->m_lfo1Rate.value() * 0.001f * m_parent->m_samplerate );
  129. m_lfo_rate[1] = ( m_parent->m_lfo2Rate.value() * 0.001f * m_parent->m_samplerate );
  130. m_lfo_inc[0] = 1.0f / m_lfo_rate[0];
  131. m_lfo_inc[1] = 1.0f / m_lfo_rate[1];
  132. m_env_sus[0] = m_parent-> m_env1Sus.value();
  133. m_env_sus[1] = m_parent-> m_env2Sus.value();
  134. m_lfovalue[0] = m_parent->m_lfo1Wave.value();
  135. m_lfovalue[1] = m_parent->m_lfo2Wave.value();
  136. m_lfoatt[0] = m_parent->m_lfo1_att;
  137. m_lfoatt[1] = m_parent->m_lfo2_att;
  138. m_env_pre[0] = m_parent->m_env1_pre;
  139. m_env_att[0] = m_parent->m_env1_att;
  140. m_env_hold[0] = m_parent->m_env1_hold;
  141. m_env_dec[0] = m_parent->m_env1_dec;
  142. m_env_rel[0] = m_parent->m_env1_rel;
  143. m_env_pre[1] = m_parent->m_env2_pre;
  144. m_env_att[1] = m_parent->m_env2_att;
  145. m_env_hold[1] = m_parent->m_env2_hold;
  146. m_env_dec[1] = m_parent->m_env2_dec;
  147. m_env_rel[1] = m_parent->m_env2_rel;
  148. // get updated osc1 values
  149. // get pulse width
  150. const float pw = ( m_parent->m_osc1Pw.value() * 0.01f );
  151. const float o1pw_e1 = ( m_parent->m_pw1env1.value() );
  152. const float o1pw_e2 = ( m_parent->m_pw1env2.value() );
  153. const float o1pw_l1 = ( m_parent->m_pw1lfo1.value() * 0.5f );
  154. const float o1pw_l2 = ( m_parent->m_pw1lfo2.value() * 0.5f );
  155. const bool o1pw_mod = o1pw_e1 != 0.0f || o1pw_e2 != 0.0f || o1pw_l1 != 0.0f || o1pw_l2 != 0.0f;
  156. // get phases
  157. const float o1lpo = m_parent->m_osc1l_po;
  158. const float o1rpo = m_parent->m_osc1r_po;
  159. const float o1p_e1 = ( m_parent->m_phs1env1.value() );
  160. const float o1p_e2 = ( m_parent->m_phs1env2.value() );
  161. const float o1p_l1 = ( m_parent->m_phs1lfo1.value() * 0.5f );
  162. const float o1p_l2 = ( m_parent->m_phs1lfo2.value() * 0.5f );
  163. const bool o1p_mod = o1p_e1 != 0.0f || o1p_e2 != 0.0f || o1p_l1 != 0.0f || o1p_l2 != 0.0f;
  164. // get pitch
  165. const float o1lfb = ( m_parent->m_osc1l_freq * m_nph->frequency() );
  166. const float o1rfb = ( m_parent->m_osc1r_freq * m_nph->frequency() );
  167. const float o1f_e1 = ( m_parent->m_pit1env1.value() * 2.0f );
  168. const float o1f_e2 = ( m_parent->m_pit1env2.value() * 2.0f );
  169. const float o1f_l1 = ( m_parent->m_pit1lfo1.value() );
  170. const float o1f_l2 = ( m_parent->m_pit1lfo2.value() );
  171. const bool o1f_mod = o1f_e1 != 0.0f || o1f_e2 != 0.0f || o1f_l1 != 0.0f || o1f_l2 != 0.0f;
  172. // get volumes
  173. const float o1lv = m_parent->m_osc1l_vol;
  174. const float o1rv = m_parent->m_osc1r_vol;
  175. const float o1v_e1 = ( m_parent->m_vol1env1.value() );
  176. const float o1v_e2 = ( m_parent->m_vol1env2.value() );
  177. const float o1v_l1 = ( m_parent->m_vol1lfo1.value() );
  178. const float o1v_l2 = ( m_parent->m_vol1lfo2.value() );
  179. const bool o1v_mod = o1v_e1 != 0.0f || o1v_e2 != 0.0f || o1v_l1 != 0.0f || o1v_l2 != 0.0f;
  180. // update osc2
  181. // get waveform
  182. const int o2w = m_parent->m_osc2Wave.value();
  183. // get phases
  184. const float o2lpo = m_parent->m_osc2l_po;
  185. const float o2rpo = m_parent->m_osc2r_po;
  186. const float o2p_e1 = ( m_parent->m_phs2env1.value() );
  187. const float o2p_e2 = ( m_parent->m_phs2env2.value() );
  188. const float o2p_l1 = ( m_parent->m_phs2lfo1.value() * 0.5f );
  189. const float o2p_l2 = ( m_parent->m_phs2lfo2.value() * 0.5f );
  190. const bool o2p_mod = o2p_e1 != 0.0f || o2p_e2 != 0.0f || o2p_l1 != 0.0f || o2p_l2 != 0.0f;
  191. // get pitch
  192. const float o2lfb = ( m_parent->m_osc2l_freq * m_nph->frequency() );
  193. const float o2rfb = ( m_parent->m_osc2r_freq * m_nph->frequency() );
  194. const float o2f_e1 = ( m_parent->m_pit2env1.value() * 2.0f );
  195. const float o2f_e2 = ( m_parent->m_pit2env2.value() * 2.0f );
  196. const float o2f_l1 = ( m_parent->m_pit2lfo1.value() );
  197. const float o2f_l2 = ( m_parent->m_pit2lfo2.value() );
  198. const bool o2f_mod = o2f_e1 != 0.0f || o2f_e2 != 0.0f || o2f_l1 != 0.0f || o2f_l2 != 0.0f;
  199. // get volumes
  200. const float o2lv = m_parent->m_osc2l_vol;
  201. const float o2rv = m_parent->m_osc2r_vol;
  202. const float o2v_e1 = ( m_parent->m_vol2env1.value() );
  203. const float o2v_e2 = ( m_parent->m_vol2env2.value() );
  204. const float o2v_l1 = ( m_parent->m_vol2lfo1.value() );
  205. const float o2v_l2 = ( m_parent->m_vol2lfo2.value() );
  206. const bool o2v_mod = o2v_e1 != 0.0f || o2v_e2 != 0.0f || o2v_l1 != 0.0f || o2v_l2 != 0.0f;
  207. // update osc3
  208. // get waveforms
  209. const int o3w1 = m_parent->m_osc3Wave1.value();
  210. const int o3w2 = m_parent->m_osc3Wave2.value();
  211. // get phases
  212. const float o3lpo = m_parent->m_osc3l_po;
  213. const float o3rpo = m_parent->m_osc3r_po;
  214. const float o3p_e1 = ( m_parent->m_phs3env1.value() );
  215. const float o3p_e2 = ( m_parent->m_phs3env2.value() );
  216. const float o3p_l1 = ( m_parent->m_phs3lfo1.value() * 0.5f );
  217. const float o3p_l2 = ( m_parent->m_phs3lfo2.value() * 0.5f );
  218. const bool o3p_mod = o3p_e1 != 0.0f || o3p_e2 != 0.0f || o3p_l1 != 0.0f || o3p_l2 != 0.0f;
  219. // get pitch modulators
  220. const float o3fb = ( m_parent->m_osc3_freq * m_nph->frequency() );
  221. const float o3f_e1 = ( m_parent->m_pit3env1.value() * 2.0f );
  222. const float o3f_e2 = ( m_parent->m_pit3env2.value() * 2.0f );
  223. const float o3f_l1 = ( m_parent->m_pit3lfo1.value() );
  224. const float o3f_l2 = ( m_parent->m_pit3lfo2.value() );
  225. const bool o3f_mod = o3f_e1 != 0.0f || o3f_e2 != 0.0f || o3f_l1 != 0.0f || o3f_l2 != 0.0f;
  226. // get volumes
  227. const float o3lv = m_parent->m_osc3l_vol;
  228. const float o3rv = m_parent->m_osc3r_vol;
  229. const float o3v_e1 = ( m_parent->m_vol3env1.value() );
  230. const float o3v_e2 = ( m_parent->m_vol3env2.value() );
  231. const float o3v_l1 = ( m_parent->m_vol3lfo1.value() );
  232. const float o3v_l2 = ( m_parent->m_vol3lfo2.value() );
  233. const bool o3v_mod = o3v_e1 != 0.0f || o3v_e2 != 0.0f || o3v_l1 != 0.0f || o3v_l2 != 0.0f;
  234. // get sub
  235. const float o3sub = ( m_parent->m_osc3Sub.value() + 100.0f ) / 200.0f;
  236. const float o3s_e1 = ( m_parent->m_sub3env1.value() );
  237. const float o3s_e2 = ( m_parent->m_sub3env2.value() );
  238. const float o3s_l1 = ( m_parent->m_sub3lfo1.value() * 0.5f );
  239. const float o3s_l2 = ( m_parent->m_sub3lfo2.value() * 0.5f );
  240. const bool o3s_mod = o3s_e1 != 0.0f || o3s_e2 != 0.0f || o3s_l1 != 0.0f || o3s_l2 != 0.0f;
  241. //o2-o3 modulation
  242. const int omod = m_parent->m_o23Mod.value();
  243. // sync information
  244. const bool o1ssr = m_parent->m_osc1SSR.value();
  245. const bool o1ssf = m_parent->m_osc1SSF.value();
  246. const bool o2sync = m_parent->m_osc2SyncH.value();
  247. const bool o3sync = m_parent->m_osc3SyncH.value();
  248. const bool o2syncr = m_parent->m_osc2SyncR.value();
  249. const bool o3syncr = m_parent->m_osc3SyncR.value();
  250. ///////////////////////////
  251. // //
  252. // start buffer loop //
  253. // //
  254. ///////////////////////////
  255. // declare working variables for for loop
  256. // phase manipulation vars - these can be reused by all oscs
  257. float leftph;
  258. float rightph;
  259. float pd_l;
  260. float pd_r;
  261. float len_l;
  262. float len_r;
  263. // osc1 vars
  264. float o1l_f;
  265. float o1r_f;
  266. float o1l_p = m_osc1l_phase + o1lpo; // we add phase offset here so we don't have to do it every frame
  267. float o1r_p = m_osc1r_phase + o1rpo; // then substract it again after loop...
  268. float o1_pw;
  269. // osc2 vars
  270. float o2l_f;
  271. float o2r_f;
  272. float o2l_p = m_osc2l_phase + o2lpo;
  273. float o2r_p = m_osc2r_phase + o2rpo;
  274. // osc3 vars
  275. float o3l_f;
  276. float o3r_f;
  277. float o3l_p = m_osc3l_phase + o3lpo;
  278. float o3r_p = m_osc3r_phase + o3rpo;
  279. float sub;
  280. // modulators
  281. float lfo[2][ m_parent->m_fpp ];
  282. float env[2][ m_parent->m_fpp ];
  283. // render modulators: envelopes, lfos
  284. updateModulators( &env[0][0], &env[1][0], &lfo[0][0], &lfo[1][0], _frames );
  285. // begin for loop
  286. for( f_cnt_t f = 0; f < _frames; ++f )
  287. {
  288. /* // debug code
  289. if( f % 10 == 0 ) {
  290. qDebug( "env1 %f -- env1 phase %f", m_env1_buf[f], m_env1_phase );
  291. qDebug( "env1 pre %f att %f dec %f rel %f ", m_parent->m_env1_pre, m_parent->m_env1_att,
  292. m_parent->m_env1_dec, m_parent->m_env1_rel );
  293. }*/
  294. /////////////////////////////
  295. // //
  296. // OSC 1 //
  297. // //
  298. /////////////////////////////
  299. // calc and mod frequencies
  300. o1l_f = o1lfb;
  301. o1r_f = o1rfb;
  302. if( o1f_mod )
  303. {
  304. modulatefreq( o1l_f, o1f )
  305. modulatefreq( o1r_f, o1f )
  306. }
  307. // calc and modulate pulse
  308. o1_pw = pw;
  309. if( o1pw_mod )
  310. {
  311. modulateabs( o1_pw, o1pw )
  312. o1_pw = qBound( PW_MIN, o1_pw, PW_MAX );
  313. }
  314. // calc and modulate phase
  315. leftph = o1l_p;
  316. rightph = o1r_p;
  317. if( o1p_mod )
  318. {
  319. modulatephs( leftph, o1p )
  320. modulatephs( rightph, o1p )
  321. }
  322. // pulse wave osc
  323. sample_t O1L = ( absFraction( leftph ) < o1_pw ) ? 1.0f : -1.0f;
  324. sample_t O1R = ( absFraction( rightph ) < o1_pw ) ? 1.0f : -1.0f;
  325. // check for rise/fall, and sync if appropriate
  326. // sync on rise
  327. if( o1ssr )
  328. {
  329. // hard sync
  330. if( o2sync )
  331. {
  332. if( O1L > m_osc1l_last ) { o2l_p = o2lpo; m_counter2l = m_parent->m_counterMax; }
  333. if( O1R > m_osc1r_last ) { o2r_p = o2rpo; m_counter2r = m_parent->m_counterMax; }
  334. }
  335. if( o3sync )
  336. {
  337. if( O1L > m_osc1l_last ) { o3l_p = o3lpo; m_counter3l = m_parent->m_counterMax; }
  338. if( O1R > m_osc1r_last ) { o3r_p = o3rpo; m_counter3r = m_parent->m_counterMax; }
  339. }
  340. // reverse sync
  341. if( o2syncr )
  342. {
  343. if( O1L > m_osc1l_last ) { m_invert2l = !m_invert2l; m_counter2l = m_parent->m_counterMax; }
  344. if( O1R > m_osc1r_last ) { m_invert2r = !m_invert2r; m_counter2r = m_parent->m_counterMax; }
  345. }
  346. if( o3syncr )
  347. {
  348. if( O1L > m_osc1l_last ) { m_invert3l = !m_invert3l; m_counter3l = m_parent->m_counterMax; }
  349. if( O1R > m_osc1r_last ) { m_invert3r = !m_invert3r; m_counter3r = m_parent->m_counterMax; }
  350. }
  351. }
  352. // sync on fall
  353. if( o1ssf )
  354. {
  355. // hard sync
  356. if( o2sync )
  357. {
  358. if( O1L < m_osc1l_last ) { o2l_p = o2lpo; m_counter2l = m_parent->m_counterMax; }
  359. if( O1R < m_osc1r_last ) { o2r_p = o2rpo; m_counter2r = m_parent->m_counterMax; }
  360. }
  361. if( o3sync )
  362. {
  363. if( O1L < m_osc1l_last ) { o3l_p = o3lpo; m_counter3l = m_parent->m_counterMax; }
  364. if( O1R < m_osc1r_last ) { o3r_p = o3rpo; m_counter3r = m_parent->m_counterMax; }
  365. }
  366. // reverse sync
  367. if( o2syncr )
  368. {
  369. if( O1L < m_osc1l_last ) { m_invert2l = !m_invert2l; m_counter2l = m_parent->m_counterMax; }
  370. if( O1R < m_osc1r_last ) { m_invert2r = !m_invert2r; m_counter2r = m_parent->m_counterMax; }
  371. }
  372. if( o3syncr )
  373. {
  374. if( O1L < m_osc1l_last ) { m_invert3l = !m_invert3l; m_counter3l = m_parent->m_counterMax; }
  375. if( O1R < m_osc1r_last ) { m_invert3r = !m_invert3r; m_counter3r = m_parent->m_counterMax; }
  376. }
  377. }
  378. // update last before signal is touched
  379. // also do a very simple amp delta cap
  380. const sample_t tmpl = m_osc1l_last;
  381. const sample_t tmpr = m_osc1r_last;
  382. m_osc1l_last = O1L;
  383. m_osc1r_last = O1R;
  384. if( tmpl != O1L ) O1L = 0.0f;
  385. if( tmpr != O1R ) O1R = 0.0f;
  386. // modulate volume
  387. O1L *= o1lv;
  388. O1R *= o1rv;
  389. if( o1v_mod )
  390. {
  391. modulatevol( O1L, o1v )
  392. modulatevol( O1R, o1v )
  393. }
  394. // update osc1 phase working variable
  395. o1l_p += 1.0f / ( static_cast<float>( m_parent->m_samplerate ) / o1l_f );
  396. o1r_p += 1.0f / ( static_cast<float>( m_parent->m_samplerate ) / o1r_f );
  397. /////////////////////////////
  398. // //
  399. // OSC 2 //
  400. // //
  401. /////////////////////////////
  402. // calc and mod frequencies
  403. o2l_f = o2lfb;
  404. o2r_f = o2rfb;
  405. if( o2f_mod )
  406. {
  407. modulatefreq( o2l_f, o2f )
  408. modulatefreq( o2r_f, o2f )
  409. }
  410. // calc and modulate phase
  411. leftph = o2l_p;
  412. rightph = o2r_p;
  413. if( o2p_mod )
  414. {
  415. modulatephs( leftph, o2p )
  416. modulatephs( rightph, o2p )
  417. }
  418. leftph = absFraction( leftph );
  419. rightph = absFraction( rightph );
  420. // phase delta
  421. pd_l = qAbs( leftph - m_ph2l_last );
  422. if( pd_l > 0.5 ) pd_l = 1.0 - pd_l;
  423. pd_r = qAbs( rightph - m_ph2r_last );
  424. if( pd_r > 0.5 ) pd_r = 1.0 - pd_r;
  425. // multi-wave DC Oscillator
  426. len_l = BandLimitedWave::pdToLen( pd_l );
  427. len_r = BandLimitedWave::pdToLen( pd_r );
  428. if( m_counter2l > 0 ) { len_l /= m_counter2l; m_counter2l--; }
  429. if( m_counter2r > 0 ) { len_r /= m_counter2r; m_counter2r--; }
  430. sample_t O2L = oscillate( o2w, leftph, len_l );
  431. sample_t O2R = oscillate( o2w, rightph, len_r );
  432. // modulate volume
  433. O2L *= o2lv;
  434. O2R *= o2rv;
  435. if( o2v_mod )
  436. {
  437. modulatevol( O2L, o2v )
  438. modulatevol( O2R, o2v )
  439. }
  440. // reverse sync - invert waveforms when needed
  441. if( m_invert2l ) O2L *= -1.0;
  442. if( m_invert2r ) O2R *= -1.0;
  443. // update osc2 phases
  444. m_ph2l_last = leftph;
  445. m_ph2r_last = rightph;
  446. o2l_p += 1.0f / ( static_cast<float>( m_parent->m_samplerate ) / o2l_f );
  447. o2r_p += 1.0f / ( static_cast<float>( m_parent->m_samplerate ) / o2r_f );
  448. /////////////////////////////
  449. // //
  450. // OSC 3 //
  451. // //
  452. /////////////////////////////
  453. // calc and mod frequencies
  454. o3l_f = o3fb;
  455. o3r_f = o3fb;
  456. if( o3f_mod )
  457. {
  458. modulatefreq( o3l_f, o3f )
  459. modulatefreq( o3r_f, o3f )
  460. }
  461. // calc and modulate phase
  462. leftph = o3l_p;
  463. rightph = o3r_p;
  464. if( o3p_mod )
  465. {
  466. modulatephs( leftph, o3p )
  467. modulatephs( rightph, o3p )
  468. }
  469. // o2 modulation?
  470. if( omod == MOD_PM )
  471. {
  472. leftph += O2L * 0.5f;
  473. rightph += O2R * 0.5f;
  474. }
  475. leftph = absFraction( leftph );
  476. rightph = absFraction( rightph );
  477. // phase delta
  478. pd_l = qAbs( leftph - m_ph3l_last );
  479. if( pd_l > 0.5 ) pd_l = 1.0 - pd_l;
  480. pd_r = qAbs( rightph - m_ph3r_last );
  481. if( pd_r > 0.5 ) pd_r = 1.0 - pd_r;
  482. // multi-wave DC Oscillator
  483. len_l = BandLimitedWave::pdToLen( pd_l );
  484. len_r = BandLimitedWave::pdToLen( pd_r );
  485. if( m_counter3l > 0 ) { len_l /= m_counter3l; m_counter3l--; }
  486. if( m_counter3r > 0 ) { len_r /= m_counter3r; m_counter3r--; }
  487. // sub-osc 1
  488. sample_t O3AL = oscillate( o3w1, leftph, len_l );
  489. sample_t O3AR = oscillate( o3w1, rightph, len_r );
  490. // multi-wave DC Oscillator, sub-osc 2
  491. sample_t O3BL = oscillate( o3w2, leftph, len_l );
  492. sample_t O3BR = oscillate( o3w2, rightph, len_r );
  493. // calc and modulate sub
  494. sub = o3sub;
  495. if( o3s_mod )
  496. {
  497. modulateabs( sub, o3s )
  498. sub = qBound( 0.0f, sub, 1.0f );
  499. }
  500. sample_t O3L = linearInterpolate( O3AL, O3BL, sub );
  501. sample_t O3R = linearInterpolate( O3AR, O3BR, sub );
  502. // modulate volume
  503. O3L *= o3lv;
  504. O3R *= o3rv;
  505. if( o3v_mod )
  506. {
  507. modulatevol( O3L, o3v )
  508. modulatevol( O3R, o3v )
  509. }
  510. // o2 modulation?
  511. if( omod == MOD_AM )
  512. {
  513. O3L = qBound( -MODCLIP, O3L * qMax( 0.0f, 1.0f + O2L ), MODCLIP );
  514. O3R = qBound( -MODCLIP, O3R * qMax( 0.0f, 1.0f + O2R ), MODCLIP );
  515. }
  516. // reverse sync - invert waveforms when needed
  517. if( m_invert3l ) O3L *= -1.0;
  518. if( m_invert3r ) O3R *= -1.0;
  519. // update osc3 phases
  520. m_ph3l_last = leftph;
  521. m_ph3r_last = rightph;
  522. len_l = 1.0f / ( static_cast<float>( m_parent->m_samplerate ) / o3l_f );
  523. len_r = 1.0f / ( static_cast<float>( m_parent->m_samplerate ) / o3r_f );
  524. // handle FM as PM
  525. if( omod == MOD_FM )
  526. {
  527. len_l += O2L * m_parent->m_fmCorrection;
  528. len_r += O2R * m_parent->m_fmCorrection;
  529. }
  530. o3l_p += len_l;
  531. o3r_p += len_r;
  532. // integrator - very simple filter
  533. sample_t L = O1L + O3L + ( omod == MOD_MIX ? O2L : 0.0f );
  534. sample_t R = O1R + O3R + ( omod == MOD_MIX ? O2R : 0.0f );
  535. _buf[f][0] = linearInterpolate( L, m_l_last, m_parent->m_integrator );
  536. _buf[f][1] = linearInterpolate( R, m_r_last, m_parent->m_integrator );
  537. m_l_last = L;
  538. m_r_last = R;
  539. }
  540. // update phases
  541. m_osc1l_phase = absFraction( o1l_p - o1lpo );
  542. m_osc1r_phase = absFraction( o1r_p - o1rpo );
  543. m_osc2l_phase = absFraction( o2l_p - o2lpo );
  544. m_osc2r_phase = absFraction( o2r_p - o2rpo );
  545. m_osc3l_phase = absFraction( o3l_p - o3lpo );
  546. m_osc3r_phase = absFraction( o3r_p - o3rpo );
  547. m_lfo_phase[0] = absFraction( m_lfo_phase[0] - lfo1_po );
  548. m_lfo_phase[1] = absFraction( m_lfo_phase[1] - lfo2_po );
  549. }
  550. inline void MonstroSynth::updateModulators( float * env1, float * env2, float * lfo1, float * lfo2, int frames )
  551. {
  552. // frames played before
  553. const f_cnt_t tfp = m_nph->totalFramesPlayed();
  554. float * lfo [2];
  555. float * env [2];
  556. lfo[0] = lfo1;
  557. lfo[1] = lfo2;
  558. env[0] = env1;
  559. env[1] = env2;
  560. for( int i = 0; i < 2; ++i )
  561. {
  562. switch( m_lfovalue[i] )
  563. {
  564. case WAVE_SINE:
  565. for( f_cnt_t f = 0; f < frames; ++f )
  566. {
  567. lfo[i][f] = Oscillator::sinSample( m_lfo_phase[i] );
  568. m_lfo_phase[i] += m_lfo_inc[i];
  569. }
  570. break;
  571. case WAVE_TRI:
  572. for( f_cnt_t f = 0; f < frames; ++f )
  573. {
  574. lfo[i][f] = Oscillator::triangleSample( m_lfo_phase[i] );
  575. m_lfo_phase[i] += m_lfo_inc[i];
  576. }
  577. break;
  578. case WAVE_SAW:
  579. for( f_cnt_t f = 0; f < frames; ++f )
  580. {
  581. lfo[i][f] = Oscillator::sawSample( m_lfo_phase[i] );
  582. m_lfo_phase[i] += m_lfo_inc[i];
  583. }
  584. break;
  585. case WAVE_RAMP:
  586. for( f_cnt_t f = 0; f < frames; ++f )
  587. {
  588. lfo[i][f] = Oscillator::sawSample( m_lfo_phase[i] ) * -1.0f;
  589. m_lfo_phase[i] += m_lfo_inc[i];
  590. }
  591. break;
  592. case WAVE_SQR:
  593. for( f_cnt_t f = 0; f < frames; ++f )
  594. {
  595. lfo[i][f] = Oscillator::squareSample( m_lfo_phase[i] );
  596. m_lfo_phase[i] += m_lfo_inc[i];
  597. }
  598. break;
  599. case WAVE_SQRSOFT:
  600. for( f_cnt_t f = 0; f < frames; ++f )
  601. {
  602. lfo[i][f] = oscillate( WAVE_SQRSOFT, m_lfo_phase[i], 0 );
  603. m_lfo_phase[i] += m_lfo_inc[i];
  604. }
  605. break;
  606. case WAVE_MOOG:
  607. for( f_cnt_t f = 0; f < frames; ++f )
  608. {
  609. lfo[i][f] = Oscillator::moogSawSample( m_lfo_phase[i] );
  610. m_lfo_phase[i] += m_lfo_inc[i];
  611. }
  612. break;
  613. case WAVE_SINABS:
  614. for( f_cnt_t f = 0; f < frames; ++f )
  615. {
  616. lfo[i][f] = oscillate( WAVE_SINABS, m_lfo_phase[i], 0 );
  617. m_lfo_phase[i] += m_lfo_inc[i];
  618. }
  619. break;
  620. case WAVE_EXP:
  621. for( f_cnt_t f = 0; f < frames; ++f )
  622. {
  623. lfo[i][f] = Oscillator::expSample( m_lfo_phase[i] );
  624. m_lfo_phase[i] += m_lfo_inc[i];
  625. }
  626. break;
  627. case WAVE_RANDOM:
  628. for( f_cnt_t f = 0; f < frames; ++f )
  629. {
  630. if( ( tfp + f ) % static_cast<int>( m_lfo_rate[i] ) == 0 ) m_lfo_last[i] = Oscillator::noiseSample( 0.0f );
  631. lfo[i][f] = m_lfo_last[i];
  632. m_lfo_phase[i] += m_lfo_inc[i];
  633. }
  634. break;
  635. case WAVE_RANDOM_SMOOTH:
  636. for( f_cnt_t f = 0; f < frames; ++f )
  637. {
  638. const f_cnt_t tm = ( tfp + f ) % static_cast<int>( m_lfo_rate[i] );
  639. if( tm == 0 )
  640. {
  641. m_lfo_last[i] = m_lfo_next[i];
  642. m_lfo_next[i] = Oscillator::noiseSample( 0.0f );
  643. }
  644. lfo[i][f] = cosinusInterpolate( m_lfo_last[i], m_lfo_next[i], static_cast<float>( tm ) / m_lfo_rate[i] );
  645. m_lfo_phase[i] += m_lfo_inc[i];
  646. }
  647. break;
  648. }
  649. // attack
  650. for( f_cnt_t f = 0; f < frames; ++f )
  651. {
  652. if( tfp + f < m_lfoatt[i] ) lfo[i][f] *= ( static_cast<sample_t>( tfp ) / m_lfoatt[i] );
  653. }
  654. /////////////////////////////////////////////
  655. // //
  656. // //
  657. // envelopes //
  658. // //
  659. // //
  660. /////////////////////////////////////////////
  661. for( f_cnt_t f = 0; f < frames; ++f )
  662. {
  663. if( m_env_phase[i] < 4.0f && m_nph->isReleased() && f >= m_nph->framesBeforeRelease() )
  664. {
  665. if( m_env_phase[i] < 1.0f ) m_env_phase[i] = 5.0f;
  666. else if( m_env_phase[i] < 2.0f ) m_env_phase[i] = 5.0f - fraction( m_env_phase[i] );
  667. else if( m_env_phase[i] < 3.0f ) m_env_phase[i] = 4.0f;
  668. else m_env_phase[i] = 4.0f + fraction( m_env_phase[i] );
  669. }
  670. // process envelope
  671. if( m_env_phase[i] < 1.0f ) // pre-delay phase
  672. {
  673. env[i][f] = 0.0f;
  674. m_env_phase[i] = qMin( 1.0f, m_env_phase[i] + m_env_pre[i] );
  675. }
  676. else if( m_env_phase[i] < 2.0f ) // attack phase
  677. {
  678. env[i][f] = calcSlope( i, fraction( m_env_phase[i] ) );
  679. m_env_phase[i] = qMin( 2.0f, m_env_phase[i] + m_env_att[i] );
  680. }
  681. else if( m_env_phase[i] < 3.0f ) // hold phase
  682. {
  683. env[i][f] = 1.0f;
  684. m_env_phase[i] = qMin( 3.0f, m_env_phase[i] + m_env_hold[i] );
  685. }
  686. else if( m_env_phase[i] < 4.0f ) // decay phase
  687. {
  688. const sample_t s = calcSlope( i, 1.0f - fraction( m_env_phase[i] ) );
  689. if( s <= m_env_sus[i] )
  690. {
  691. env[i][f] = m_env_sus[i];
  692. }
  693. else
  694. {
  695. env[i][f] = s;
  696. m_env_phase[i] = qMin( 4.0f - m_env_sus[i], m_env_phase[i] + m_env_dec[i] );
  697. if( m_env_phase[i] == 4.0f ) m_env_phase[i] = 5.0f; // jump over release if sustain is zero - fix for clicking
  698. }
  699. }
  700. else if( m_env_phase[i] < 5.0f ) // release phase
  701. {
  702. env[i][f] = calcSlope( i, 1.0f - fraction( m_env_phase[i] ) );
  703. m_env_phase[i] += m_env_rel[i];
  704. }
  705. else env[i][f] = 0.0f;
  706. }
  707. }
  708. }
  709. inline sample_t MonstroSynth::calcSlope( int slope, sample_t s )
  710. {
  711. if( m_parent->m_slope[slope] == 1.0f ) return s;
  712. if( s == 0.0f ) return s;
  713. return fastPow( s, m_parent->m_slope[slope] );
  714. }
  715. MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) :
  716. Instrument( _instrument_track, &monstro_plugin_descriptor ),
  717. m_osc1Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 1 Volume" ) ),
  718. m_osc1Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 1 Panning" ) ),
  719. m_osc1Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 1 Coarse detune" ) ),
  720. m_osc1Ftl( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 Fine detune left" ) ),
  721. m_osc1Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 1 Fine detune right" ) ),
  722. m_osc1Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 1 Stereo phase offset" ) ),
  723. m_osc1Pw( 50.0, PW_MIN, PW_MAX, 0.01, this, tr( "Osc 1 Pulse width" ) ),
  724. m_osc1SSR( false, this, tr( "Osc 1 Sync send on rise" ) ),
  725. m_osc1SSF( false, this, tr( "Osc 1 Sync send on fall" ) ),
  726. m_osc2Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 2 Volume" ) ),
  727. m_osc2Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 2 Panning" ) ),
  728. m_osc2Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 2 Coarse detune" ) ),
  729. m_osc2Ftl( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 Fine detune left" ) ),
  730. m_osc2Ftr( 0.0, -100.0, 100.0, 1.0, this, tr( "Osc 2 Fine detune right" ) ),
  731. m_osc2Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 2 Stereo phase offset" ) ),
  732. m_osc2Wave( this, tr( "Osc 2 Waveform" ) ),
  733. m_osc2SyncH( false, this, tr( "Osc 2 Sync Hard" ) ),
  734. m_osc2SyncR( false, this, tr( "Osc 2 Sync Reverse" ) ),
  735. m_osc3Vol( 33.0, 0.0, 200.0, 0.1, this, tr( "Osc 3 Volume" ) ),
  736. m_osc3Pan( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Panning" ) ),
  737. m_osc3Crs( 0.0, -24.0, 24.0, 1.0, this, tr( "Osc 3 Coarse detune" ) ),
  738. m_osc3Spo( 0.0, -180.0, 180.0, 0.1, this, tr( "Osc 3 Stereo phase offset" ) ),
  739. m_osc3Sub( 0.0, -100.0, 100.0, 0.1, this, tr( "Osc 3 Sub-oscillator mix" ) ),
  740. m_osc3Wave1( this, tr( "Osc 3 Waveform 1" ) ),
  741. m_osc3Wave2( this, tr( "Osc 3 Waveform 2" ) ),
  742. m_osc3SyncH( false, this, tr( "Osc 3 Sync Hard" ) ),
  743. m_osc3SyncR( false, this, tr( "Osc 3 Sync Reverse" ) ),
  744. m_lfo1Wave( this, tr( "LFO 1 Waveform" ) ),
  745. m_lfo1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 1 Attack" ) ),
  746. m_lfo1Rate( 1.0f, 0.1, 10000.0, 0.1, 10000.0f, this, tr( "LFO 1 Rate" ) ),
  747. m_lfo1Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 1 Phase" ) ),
  748. m_lfo2Wave( this, tr( "LFO 2 Waveform" ) ),
  749. m_lfo2Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "LFO 2 Attack" ) ),
  750. m_lfo2Rate( 1.0f, 0.1, 10000.0, 0.1, 10000.0f, this, tr( "LFO 2 Rate" ) ),
  751. m_lfo2Phs( 0.0, -180.0, 180.0, 0.1, this, tr( "LFO 2 Phase" ) ),
  752. m_env1Pre( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Pre-delay" ) ),
  753. m_env1Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 1 Attack" ) ),
  754. m_env1Hold( 0.0f, 0.0f, 4000.0f, 1.0f, 4000.0f, this, tr( "Env 1 Hold" ) ),
  755. m_env1Dec( 0.0f, 0.0f, 4000.0f, 1.0f, 4000.0f, this, tr( "Env 1 Decay" ) ),
  756. m_env1Sus( 1.0f, 0.0f, 1.0f, 0.001f, this, tr( "Env 1 Sustain" ) ),
  757. m_env1Rel( 0.0f, 0.0f, 4000.0f, 1.0f, 4000.0f, this, tr( "Env 1 Release" ) ),
  758. m_env1Slope( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Env 1 Slope" ) ),
  759. m_env2Pre( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 2 Pre-delay" ) ),
  760. m_env2Att( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "Env 2 Attack" ) ),
  761. m_env2Hold( 0.0f, 0.0f, 4000.0f, 1.0f, 4000.0f, this, tr( "Env 2 Hold" ) ),
  762. m_env2Dec( 0.0f, 0.0f, 4000.0f, 1.0f, 4000.0f, this, tr( "Env 2 Decay" ) ),
  763. m_env2Sus( 1.0f, 0.0f, 1.0f, 0.001f, this, tr( "Env 2 Sustain" ) ),
  764. m_env2Rel( 0.0f, 0.0f, 4000.0f, 1.0f, 4000.0f, this, tr( "Env 2 Release" ) ),
  765. m_env2Slope( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Env 2 Slope" ) ),
  766. m_o23Mod( 0, 0, NUM_MODS - 1, this, tr( "Osc2-3 modulation" ) ),
  767. m_selectedView( 0, 0, 1, this, tr( "Selected view" ) ),
  768. m_vol1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-Env1" ) ),
  769. m_vol1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-Env2" ) ),
  770. m_vol1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-LFO1" ) ),
  771. m_vol1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol1-LFO2" ) ),
  772. m_vol2env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-Env1" ) ),
  773. m_vol2env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-Env2" ) ),
  774. m_vol2lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-LFO1" ) ),
  775. m_vol2lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol2-LFO2" ) ),
  776. m_vol3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-Env1" ) ),
  777. m_vol3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-Env2" ) ),
  778. m_vol3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-LFO1" ) ),
  779. m_vol3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Vol3-LFO2" ) ),
  780. m_phs1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-Env1" ) ),
  781. m_phs1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-Env2" ) ),
  782. m_phs1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-LFO1" ) ),
  783. m_phs1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs1-LFO2" ) ),
  784. m_phs2env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-Env1" ) ),
  785. m_phs2env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-Env2" ) ),
  786. m_phs2lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-LFO1" ) ),
  787. m_phs2lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs2-LFO2" ) ),
  788. m_phs3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-Env1" ) ),
  789. m_phs3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-Env2" ) ),
  790. m_phs3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-LFO1" ) ),
  791. m_phs3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Phs3-LFO2" ) ),
  792. m_pit1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-Env1" ) ),
  793. m_pit1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-Env2" ) ),
  794. m_pit1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-LFO1" ) ),
  795. m_pit1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit1-LFO2" ) ),
  796. m_pit2env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-Env1" ) ),
  797. m_pit2env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-Env2" ) ),
  798. m_pit2lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-LFO1" ) ),
  799. m_pit2lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit2-LFO2" ) ),
  800. m_pit3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-Env1" ) ),
  801. m_pit3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-Env2" ) ),
  802. m_pit3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-LFO1" ) ),
  803. m_pit3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Pit3-LFO2" ) ),
  804. m_pw1env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-Env1" ) ),
  805. m_pw1env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-Env2" ) ),
  806. m_pw1lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-LFO1" ) ),
  807. m_pw1lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "PW1-LFO2" ) ),
  808. m_sub3env1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-Env1" ) ),
  809. m_sub3env2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-Env2" ) ),
  810. m_sub3lfo1( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-LFO1" ) ),
  811. m_sub3lfo2( 0.0f, -1.0f, 1.0f, 0.001f, this, tr( "Sub3-LFO2" ) )
  812. {
  813. // setup waveboxes
  814. setwavemodel( m_osc2Wave )
  815. setwavemodel( m_osc3Wave1 )
  816. setwavemodel( m_osc3Wave2 )
  817. setlfowavemodel( m_lfo1Wave )
  818. setlfowavemodel( m_lfo2Wave )
  819. // make connections:
  820. // updateVolumes
  821. connect( &m_osc1Vol, SIGNAL( dataChanged() ), this, SLOT( updateVolume1() ) );
  822. connect( &m_osc1Pan, SIGNAL( dataChanged() ), this, SLOT( updateVolume1() ) );
  823. connect( &m_osc2Vol, SIGNAL( dataChanged() ), this, SLOT( updateVolume2() ) );
  824. connect( &m_osc2Pan, SIGNAL( dataChanged() ), this, SLOT( updateVolume2() ) );
  825. connect( &m_osc3Vol, SIGNAL( dataChanged() ), this, SLOT( updateVolume3() ) );
  826. connect( &m_osc3Pan, SIGNAL( dataChanged() ), this, SLOT( updateVolume3() ) );
  827. // updateFreq
  828. connect( &m_osc1Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq1() ) );
  829. connect( &m_osc2Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq2() ) );
  830. connect( &m_osc3Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq3() ) );
  831. connect( &m_osc1Ftl, SIGNAL( dataChanged() ), this, SLOT( updateFreq1() ) );
  832. connect( &m_osc2Ftl, SIGNAL( dataChanged() ), this, SLOT( updateFreq2() ) );
  833. connect( &m_osc1Ftr, SIGNAL( dataChanged() ), this, SLOT( updateFreq1() ) );
  834. connect( &m_osc2Ftr, SIGNAL( dataChanged() ), this, SLOT( updateFreq2() ) );
  835. // updatePO
  836. connect( &m_osc1Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO1() ) );
  837. connect( &m_osc2Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO2() ) );
  838. connect( &m_osc3Spo, SIGNAL( dataChanged() ), this, SLOT( updatePO3() ) );
  839. // updateEnvelope1
  840. connect( &m_env1Pre, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) );
  841. connect( &m_env1Att, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) );
  842. connect( &m_env1Hold, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) );
  843. connect( &m_env1Dec, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) );
  844. connect( &m_env1Rel, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope1() ) );
  845. connect( &m_env1Slope, SIGNAL( dataChanged() ), this, SLOT( updateSlope1() ) );
  846. // updateEnvelope2
  847. connect( &m_env2Pre, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) );
  848. connect( &m_env2Att, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) );
  849. connect( &m_env2Hold, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) );
  850. connect( &m_env2Dec, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) );
  851. connect( &m_env2Rel, SIGNAL( dataChanged() ), this, SLOT( updateEnvelope2() ) );
  852. connect( &m_env2Slope, SIGNAL( dataChanged() ), this, SLOT( updateSlope2() ) );
  853. // updateLFOAtts
  854. connect( &m_lfo1Att, SIGNAL( dataChanged() ), this, SLOT( updateLFOAtts() ) );
  855. connect( &m_lfo2Att, SIGNAL( dataChanged() ), this, SLOT( updateLFOAtts() ) );
  856. // updateSampleRate
  857. connect( Engine::mixer(), SIGNAL( sampleRateChanged() ), this, SLOT( updateSamplerate() ) );
  858. m_fpp = Engine::mixer()->framesPerPeriod();
  859. updateSamplerate();
  860. updateVolume1();
  861. updateVolume2();
  862. updateVolume3();
  863. updateFreq1();
  864. updateFreq2();
  865. updateFreq3();
  866. updatePO1();
  867. updatePO2();
  868. updatePO3();
  869. updateSlope1();
  870. updateSlope2();
  871. }
  872. MonstroInstrument::~MonstroInstrument()
  873. {
  874. }
  875. void MonstroInstrument::playNote( NotePlayHandle * _n,
  876. sampleFrame * _working_buffer )
  877. {
  878. const fpp_t frames = _n->framesLeftForCurrentPeriod();
  879. const f_cnt_t offset = _n->noteOffset();
  880. if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL )
  881. {
  882. _n->m_pluginData = new MonstroSynth( this, _n );
  883. }
  884. MonstroSynth * ms = static_cast<MonstroSynth *>( _n->m_pluginData );
  885. ms->renderOutput( frames, _working_buffer + offset );
  886. //applyRelease( _working_buffer, _n ); // we have our own release
  887. instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n );
  888. }
  889. void MonstroInstrument::deleteNotePluginData( NotePlayHandle * _n )
  890. {
  891. delete static_cast<MonstroSynth *>( _n->m_pluginData );
  892. }
  893. void MonstroInstrument::saveSettings( QDomDocument & _doc,
  894. QDomElement & _this )
  895. {
  896. m_osc1Vol.saveSettings( _doc, _this, "o1vol" );
  897. m_osc1Pan.saveSettings( _doc, _this, "o1pan" );
  898. m_osc1Crs.saveSettings( _doc, _this, "o1crs" );
  899. m_osc1Ftl.saveSettings( _doc, _this, "o1ftl" );
  900. m_osc1Ftr.saveSettings( _doc, _this, "o1ftr" );
  901. m_osc1Spo.saveSettings( _doc, _this, "o1spo" );
  902. m_osc1Pw.saveSettings( _doc, _this, "o1pw" );
  903. m_osc1SSR.saveSettings( _doc, _this, "o1ssr" );
  904. m_osc1SSF.saveSettings( _doc, _this, "o1ssf" );
  905. m_osc2Vol.saveSettings( _doc, _this, "o2vol" );
  906. m_osc2Pan.saveSettings( _doc, _this, "o2pan" );
  907. m_osc2Crs.saveSettings( _doc, _this, "o2crs" );
  908. m_osc2Ftl.saveSettings( _doc, _this, "o2ftl" );
  909. m_osc2Ftr.saveSettings( _doc, _this, "o2ftr" );
  910. m_osc2Spo.saveSettings( _doc, _this, "o2spo" );
  911. m_osc2Wave.saveSettings( _doc, _this, "o2wav" );
  912. m_osc2SyncH.saveSettings( _doc, _this, "o2syn" );
  913. m_osc2SyncR.saveSettings( _doc, _this, "o2synr" );
  914. m_osc3Vol.saveSettings( _doc, _this, "o3vol" );
  915. m_osc3Pan.saveSettings( _doc, _this, "o3pan" );
  916. m_osc3Crs.saveSettings( _doc, _this, "o3crs" );
  917. m_osc3Spo.saveSettings( _doc, _this, "o3spo" );
  918. m_osc3Sub.saveSettings( _doc, _this, "o3sub" );
  919. m_osc3Wave1.saveSettings( _doc, _this, "o3wav1" );
  920. m_osc3Wave2.saveSettings( _doc, _this, "o3wav2" );
  921. m_osc3SyncH.saveSettings( _doc, _this, "o3syn" );
  922. m_osc3SyncR.saveSettings( _doc, _this, "o3synr" );
  923. m_lfo1Wave.saveSettings( _doc, _this, "l1wav" );
  924. m_lfo1Att.saveSettings( _doc, _this, "l1att" );
  925. m_lfo1Rate.saveSettings( _doc, _this, "l1rat" );
  926. m_lfo1Phs.saveSettings( _doc, _this, "l1phs" );
  927. m_lfo2Wave.saveSettings( _doc, _this, "l2wav" );
  928. m_lfo2Att.saveSettings( _doc, _this, "l2att" );
  929. m_lfo2Rate.saveSettings( _doc, _this, "l2rat" );
  930. m_lfo2Phs.saveSettings( _doc, _this, "l2phs" );
  931. m_env1Pre.saveSettings( _doc, _this, "e1pre" );
  932. m_env1Att.saveSettings( _doc, _this, "e1att" );
  933. m_env1Hold.saveSettings( _doc, _this, "e1hol" );
  934. m_env1Dec.saveSettings( _doc, _this, "e1dec" );
  935. m_env1Sus.saveSettings( _doc, _this, "e1sus" );
  936. m_env1Rel.saveSettings( _doc, _this, "e1rel" );
  937. m_env1Slope.saveSettings( _doc, _this, "e1slo" );
  938. m_env2Pre.saveSettings( _doc, _this, "e2pre" );
  939. m_env2Att.saveSettings( _doc, _this, "e2att" );
  940. m_env2Hold.saveSettings( _doc, _this, "e2hol" );
  941. m_env2Dec.saveSettings( _doc, _this, "e2dec" );
  942. m_env2Sus.saveSettings( _doc, _this, "e2sus" );
  943. m_env2Rel.saveSettings( _doc, _this, "e2rel" );
  944. m_env2Slope.saveSettings( _doc, _this, "e2slo" );
  945. m_o23Mod.saveSettings( _doc, _this, "o23mo" );
  946. m_vol1env1.saveSettings( _doc, _this, "v1e1" );
  947. m_vol1env2.saveSettings( _doc, _this, "v1e2" );
  948. m_vol1lfo1.saveSettings( _doc, _this, "v1l1" );
  949. m_vol1lfo2.saveSettings( _doc, _this, "v1l2" );
  950. m_vol2env1.saveSettings( _doc, _this, "v2e1" );
  951. m_vol2env2.saveSettings( _doc, _this, "v2e2" );
  952. m_vol2lfo1.saveSettings( _doc, _this, "v2l1" );
  953. m_vol2lfo2.saveSettings( _doc, _this, "v2l2" );
  954. m_vol3env1.saveSettings( _doc, _this, "v3e1" );
  955. m_vol3env2.saveSettings( _doc, _this, "v3e2" );
  956. m_vol3lfo1.saveSettings( _doc, _this, "v3l1" );
  957. m_vol3lfo2.saveSettings( _doc, _this, "v3l2" );
  958. m_phs1env1.saveSettings( _doc, _this, "p1e1" );
  959. m_phs1env2.saveSettings( _doc, _this, "p1e2" );
  960. m_phs1lfo1.saveSettings( _doc, _this, "p1l1" );
  961. m_phs1lfo2.saveSettings( _doc, _this, "p1l2" );
  962. m_phs2env1.saveSettings( _doc, _this, "p2e1" );
  963. m_phs2env2.saveSettings( _doc, _this, "p2e2" );
  964. m_phs2lfo1.saveSettings( _doc, _this, "p2l1" );
  965. m_phs2lfo2.saveSettings( _doc, _this, "p2l2" );
  966. m_phs3env1.saveSettings( _doc, _this, "p3e1" );
  967. m_phs3env2.saveSettings( _doc, _this, "p3e2" );
  968. m_phs3lfo1.saveSettings( _doc, _this, "p3l1" );
  969. m_phs3lfo2.saveSettings( _doc, _this, "p3l2" );
  970. m_pit1env1.saveSettings( _doc, _this, "f1e1" );
  971. m_pit1env2.saveSettings( _doc, _this, "f1e2" );
  972. m_pit1lfo1.saveSettings( _doc, _this, "f1l1" );
  973. m_pit1lfo2.saveSettings( _doc, _this, "f1l2" );
  974. m_pit2env1.saveSettings( _doc, _this, "f2e1" );
  975. m_pit2env2.saveSettings( _doc, _this, "f2e2" );
  976. m_pit2lfo1.saveSettings( _doc, _this, "f2l1" );
  977. m_pit2lfo2.saveSettings( _doc, _this, "f2l2" );
  978. m_pit3env1.saveSettings( _doc, _this, "f3e1" );
  979. m_pit3env2.saveSettings( _doc, _this, "f3e2" );
  980. m_pit3lfo1.saveSettings( _doc, _this, "f3l1" );
  981. m_pit3lfo2.saveSettings( _doc, _this, "f3l2" );
  982. m_pw1env1.saveSettings( _doc, _this, "w1e1" );
  983. m_pw1env2.saveSettings( _doc, _this, "w1e2" );
  984. m_pw1lfo1.saveSettings( _doc, _this, "w1l1" );
  985. m_pw1lfo2.saveSettings( _doc, _this, "w1l2" );
  986. m_sub3env1.saveSettings( _doc, _this, "s3e1" );
  987. m_sub3env2.saveSettings( _doc, _this, "s3e2" );
  988. m_sub3lfo1.saveSettings( _doc, _this, "s3l1" );
  989. m_sub3lfo2.saveSettings( _doc, _this, "s3l2" );
  990. }
  991. void MonstroInstrument::loadSettings( const QDomElement & _this )
  992. {
  993. m_osc1Vol.loadSettings( _this, "o1vol" );
  994. m_osc1Pan.loadSettings( _this, "o1pan" );
  995. m_osc1Crs.loadSettings( _this, "o1crs" );
  996. m_osc1Ftl.loadSettings( _this, "o1ftl" );
  997. m_osc1Ftr.loadSettings( _this, "o1ftr" );
  998. m_osc1Spo.loadSettings( _this, "o1spo" );
  999. m_osc1Pw.loadSettings( _this, "o1pw" );
  1000. m_osc1SSR.loadSettings( _this, "o1ssr" );
  1001. m_osc1SSF.loadSettings( _this, "o1ssf" );
  1002. m_osc2Vol.loadSettings( _this, "o2vol" );
  1003. m_osc2Pan.loadSettings( _this, "o2pan" );
  1004. m_osc2Crs.loadSettings( _this, "o2crs" );
  1005. m_osc2Ftl.loadSettings( _this, "o2ftl" );
  1006. m_osc2Ftr.loadSettings( _this, "o2ftr" );
  1007. m_osc2Spo.loadSettings( _this, "o2spo" );
  1008. m_osc2Wave.loadSettings( _this, "o2wav" );
  1009. m_osc2SyncH.loadSettings( _this, "o2syn" );
  1010. m_osc2SyncR.loadSettings( _this, "o2synr" );
  1011. m_osc3Vol.loadSettings( _this, "o3vol" );
  1012. m_osc3Pan.loadSettings( _this, "o3pan" );
  1013. m_osc3Crs.loadSettings( _this, "o3crs" );
  1014. m_osc3Spo.loadSettings( _this, "o3spo" );
  1015. m_osc3Sub.loadSettings( _this, "o3sub" );
  1016. m_osc3Wave1.loadSettings( _this, "o3wav1" );
  1017. m_osc3Wave2.loadSettings( _this, "o3wav2" );
  1018. m_osc3SyncH.loadSettings( _this, "o3syn" );
  1019. m_osc3SyncR.loadSettings( _this, "o3synr" );
  1020. m_lfo1Wave.loadSettings( _this, "l1wav" );
  1021. m_lfo1Att.loadSettings( _this, "l1att" );
  1022. m_lfo1Rate.loadSettings( _this, "l1rat" );
  1023. m_lfo1Phs.loadSettings( _this, "l1phs" );
  1024. m_lfo2Wave.loadSettings( _this, "l2wav" );
  1025. m_lfo2Att.loadSettings( _this, "l2att" );
  1026. m_lfo2Rate.loadSettings( _this, "l2rat" );
  1027. m_lfo2Phs.loadSettings( _this, "l2phs" );
  1028. m_env1Pre.loadSettings( _this, "e1pre" );
  1029. m_env1Att.loadSettings( _this, "e1att" );
  1030. m_env1Hold.loadSettings( _this, "e1hol" );
  1031. m_env1Dec.loadSettings( _this, "e1dec" );
  1032. m_env1Sus.loadSettings( _this, "e1sus" );
  1033. m_env1Rel.loadSettings( _this, "e1rel" );
  1034. m_env1Slope.loadSettings( _this, "e1slo" );
  1035. m_env2Pre.loadSettings( _this, "e2pre" );
  1036. m_env2Att.loadSettings( _this, "e2att" );
  1037. m_env2Hold.loadSettings( _this, "e2hol" );
  1038. m_env2Dec.loadSettings( _this, "e2dec" );
  1039. m_env2Sus.loadSettings( _this, "e2sus" );
  1040. m_env2Rel.loadSettings( _this, "e2rel" );
  1041. m_env2Slope.loadSettings( _this, "e2slo" );
  1042. m_o23Mod.loadSettings( _this, "o23mo" );
  1043. m_vol1env1.loadSettings( _this, "v1e1" );
  1044. m_vol1env2.loadSettings( _this, "v1e2" );
  1045. m_vol1lfo1.loadSettings( _this, "v1l1" );
  1046. m_vol1lfo2.loadSettings( _this, "v1l2" );
  1047. m_vol2env1.loadSettings( _this, "v2e1" );
  1048. m_vol2env2.loadSettings( _this, "v2e2" );
  1049. m_vol2lfo1.loadSettings( _this, "v2l1" );
  1050. m_vol2lfo2.loadSettings( _this, "v2l2" );
  1051. m_vol3env1.loadSettings( _this, "v3e1" );
  1052. m_vol3env2.loadSettings( _this, "v3e2" );
  1053. m_vol3lfo1.loadSettings( _this, "v3l1" );
  1054. m_vol3lfo2.loadSettings( _this, "v3l2" );
  1055. m_phs1env1.loadSettings( _this, "p1e1" );
  1056. m_phs1env2.loadSettings( _this, "p1e2" );
  1057. m_phs1lfo1.loadSettings( _this, "p1l1" );
  1058. m_phs1lfo2.loadSettings( _this, "p1l2" );
  1059. m_phs2env1.loadSettings( _this, "p2e1" );
  1060. m_phs2env2.loadSettings( _this, "p2e2" );
  1061. m_phs2lfo1.loadSettings( _this, "p2l1" );
  1062. m_phs2lfo2.loadSettings( _this, "p2l2" );
  1063. m_phs3env1.loadSettings( _this, "p3e1" );
  1064. m_phs3env2.loadSettings( _this, "p3e2" );
  1065. m_phs3lfo1.loadSettings( _this, "p3l1" );
  1066. m_phs3lfo2.loadSettings( _this, "p3l2" );
  1067. m_pit1env1.loadSettings( _this, "f1e1" );
  1068. m_pit1env2.loadSettings( _this, "f1e2" );
  1069. m_pit1lfo1.loadSettings( _this, "f1l1" );
  1070. m_pit1lfo2.loadSettings( _this, "f1l2" );
  1071. m_pit2env1.loadSettings( _this, "f2e1" );
  1072. m_pit2env2.loadSettings( _this, "f2e2" );
  1073. m_pit2lfo1.loadSettings( _this, "f2l1" );
  1074. m_pit2lfo2.loadSettings( _this, "f2l2" );
  1075. m_pit3env1.loadSettings( _this, "f3e1" );
  1076. m_pit3env2.loadSettings( _this, "f3e2" );
  1077. m_pit3lfo1.loadSettings( _this, "f3l1" );
  1078. m_pit3lfo2.loadSettings( _this, "f3l2" );
  1079. m_pw1env1.loadSettings( _this, "w1e1" );
  1080. m_pw1env2.loadSettings( _this, "w1e2" );
  1081. m_pw1lfo1.loadSettings( _this, "w1l1" );
  1082. m_pw1lfo2.loadSettings( _this, "w1l2" );
  1083. m_sub3env1.loadSettings( _this, "s3e1" );
  1084. m_sub3env2.loadSettings( _this, "s3e2" );
  1085. m_sub3lfo1.loadSettings( _this, "s3l1" );
  1086. m_sub3lfo2.loadSettings( _this, "s3l2" );
  1087. }
  1088. QString MonstroInstrument::nodeName() const
  1089. {
  1090. return monstro_plugin_descriptor.name;
  1091. }
  1092. f_cnt_t MonstroInstrument::desiredReleaseFrames() const
  1093. {
  1094. return qMax( 64, qMax( m_env1_relF, m_env2_relF ) );
  1095. }
  1096. PluginView * MonstroInstrument::instantiateView( QWidget * _parent )
  1097. {
  1098. return( new MonstroView( this, _parent ) );
  1099. }
  1100. void MonstroInstrument::updateVolume1()
  1101. {
  1102. m_osc1l_vol = leftCh( m_osc1Vol.value(), m_osc1Pan.value() );
  1103. m_osc1r_vol = rightCh( m_osc1Vol.value(), m_osc1Pan.value() );
  1104. }
  1105. void MonstroInstrument::updateVolume2()
  1106. {
  1107. m_osc2l_vol = leftCh( m_osc2Vol.value(), m_osc2Pan.value() );
  1108. m_osc2r_vol = rightCh( m_osc2Vol.value(), m_osc2Pan.value() );
  1109. }
  1110. void MonstroInstrument::updateVolume3()
  1111. {
  1112. m_osc3l_vol = leftCh( m_osc3Vol.value(), m_osc3Pan.value() );
  1113. m_osc3r_vol = rightCh( m_osc3Vol.value(), m_osc3Pan.value() );
  1114. }
  1115. void MonstroInstrument::updateFreq1()
  1116. {
  1117. m_osc1l_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) *
  1118. powf( 2.0f, m_osc1Ftl.value() / 1200.0f );
  1119. m_osc1r_freq = powf( 2.0f, m_osc1Crs.value() / 12.0f ) *
  1120. powf( 2.0f, m_osc1Ftr.value() / 1200.0f );
  1121. }
  1122. void MonstroInstrument::updateFreq2()
  1123. {
  1124. m_osc2l_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) *
  1125. powf( 2.0f, m_osc2Ftl.value() / 1200.0f );
  1126. m_osc2r_freq = powf( 2.0f, m_osc2Crs.value() / 12.0f ) *
  1127. powf( 2.0f, m_osc2Ftr.value() / 1200.0f );
  1128. }
  1129. void MonstroInstrument::updateFreq3()
  1130. {
  1131. m_osc3_freq = powf( 2.0f, m_osc3Crs.value() / 12.0f );
  1132. }
  1133. void MonstroInstrument::updatePO1()
  1134. {
  1135. m_osc1l_po = m_osc1Spo.value() / 720.0f;
  1136. m_osc1r_po = ( m_osc1Spo.value() * -1.0 ) / 720.0f;
  1137. }
  1138. void MonstroInstrument::updatePO2()
  1139. {
  1140. m_osc2l_po = m_osc2Spo.value() / 720.0f;
  1141. m_osc2r_po = ( m_osc2Spo.value() * -1.0 ) / 720.0f;
  1142. }
  1143. void MonstroInstrument::updatePO3()
  1144. {
  1145. m_osc3l_po = m_osc3Spo.value() / 720.0f;
  1146. m_osc3r_po = ( m_osc3Spo.value() * -1.0 ) / 720.0f;
  1147. }
  1148. void MonstroInstrument::updateEnvelope1()
  1149. {
  1150. if( m_env1Pre.value() == 0.0f ) m_env1_pre = 1.0;
  1151. else m_env1_pre = 1.0f / ( m_env1Pre.value() / 1000.0f ) / m_samplerate;
  1152. if( m_env1Att.value() == 0.0f ) m_env1_att = 1.0;
  1153. else m_env1_att = 1.0f / ( m_env1Att.value() / 1000.0f ) / m_samplerate;
  1154. if( m_env1Hold.value() == 0.0f ) m_env1_hold = 1.0;
  1155. else m_env1_hold = 1.0f / ( m_env1Hold.value() / 1000.0f ) / m_samplerate;
  1156. if( m_env1Dec.value() == 0.0f ) m_env1_dec = 1.0;
  1157. else m_env1_dec = 1.0f / ( m_env1Dec.value() / 1000.0f ) / m_samplerate;
  1158. if( m_env1Rel.value() == 0.0f ) m_env1_rel = 1.0;
  1159. else m_env1_rel = 1.0f / ( m_env1Rel.value() / 1000.0f ) / m_samplerate;
  1160. m_env1_len = ( m_env1Pre.value() + m_env1Att.value() + m_env1Hold.value() + m_env1Dec.value() ) * m_samplerate / 1000.0f;
  1161. m_env1_relF = m_env1Rel.value() * m_samplerate / 1000.0f;
  1162. }
  1163. void MonstroInstrument::updateEnvelope2()
  1164. {
  1165. if( m_env2Pre.value() == 0.0f ) m_env2_pre = 1.0;
  1166. else m_env2_pre = 1.0f / ( m_env2Pre.value() / 1000.0f ) / m_samplerate;
  1167. if( m_env2Att.value() == 0.0f ) m_env2_att = 1.0;
  1168. else m_env2_att = 1.0f / ( m_env2Att.value() / 1000.0f ) / m_samplerate;
  1169. if( m_env2Hold.value() == 0.0f ) m_env2_hold = 1.0;
  1170. else m_env2_hold = 1.0f / ( m_env2Hold.value() / 1000.0f ) / m_samplerate;
  1171. if( m_env2Dec.value() == 0.0f ) m_env2_dec = 1.0;
  1172. else m_env2_dec = 1.0f / ( m_env2Dec.value() / 1000.0f ) / m_samplerate;
  1173. if( m_env2Rel.value() == 0.0f ) m_env2_rel = 1.0;
  1174. else m_env2_rel = 1.0f / ( m_env2Rel.value() / 1000.0f ) / m_samplerate;
  1175. m_env2_len = ( m_env2Pre.value() + m_env2Att.value() + m_env2Hold.value() + m_env2Dec.value() ) * m_samplerate / 1000.0f;
  1176. m_env2_relF = m_env2Rel.value() * m_samplerate / 1000.0f;
  1177. }
  1178. void MonstroInstrument::updateLFOAtts()
  1179. {
  1180. m_lfo1_att = m_lfo1Att.value() * m_samplerate / 1000.0f;
  1181. m_lfo2_att = m_lfo2Att.value() * m_samplerate / 1000.0f;
  1182. }
  1183. void MonstroInstrument::updateSamplerate()
  1184. {
  1185. m_samplerate = Engine::mixer()->processingSampleRate();
  1186. m_integrator = 0.5f - ( 0.5f - INTEGRATOR ) * 44100.0f / m_samplerate;
  1187. m_fmCorrection = 44100.f / m_samplerate * FM_AMOUNT;
  1188. m_counterMax = ( m_samplerate * 5 ) / 44100;
  1189. updateEnvelope1();
  1190. updateEnvelope2();
  1191. updateLFOAtts();
  1192. }
  1193. void MonstroInstrument::updateSlope1()
  1194. {
  1195. const float slope = m_env1Slope.value();
  1196. m_slope[0] = exp10f( slope * -1.0f );
  1197. }
  1198. void MonstroInstrument::updateSlope2()
  1199. {
  1200. const float slope = m_env2Slope.value();
  1201. m_slope[1] = exp10f( slope * -1.0f );
  1202. }
  1203. MonstroView::MonstroView( Instrument * _instrument,
  1204. QWidget * _parent ) :
  1205. InstrumentView( _instrument, _parent )
  1206. {
  1207. m_operatorsView = setupOperatorsView( this );
  1208. setWidgetBackground( m_operatorsView, "artwork_op" );
  1209. m_operatorsView->show();
  1210. m_operatorsView->move( 0, 0 );
  1211. m_matrixView = setupMatrixView( this );
  1212. setWidgetBackground( m_matrixView, "artwork_mat" );
  1213. m_matrixView->hide();
  1214. m_matrixView->move( 0, 0 );
  1215. // "tab buttons"
  1216. PixmapButton * m_opViewButton = new PixmapButton( this, NULL );
  1217. m_opViewButton -> move( 0,0 );
  1218. m_opViewButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "opview_active" ) );
  1219. m_opViewButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "opview_inactive" ) );
  1220. ToolTip::add( m_opViewButton, tr( "Operators view" ) );
  1221. m_opViewButton -> setWhatsThis( tr( "The Operators view contains all the operators. These include both audible "
  1222. "operators (oscillators) and inaudible operators, or modulators: "
  1223. "Low-frequency oscillators and Envelopes. \n\n"
  1224. "Knobs and other widgets in the Operators view have their own what's this -texts, "
  1225. "so you can get more specific help for them that way. " ) );
  1226. PixmapButton * m_matViewButton = new PixmapButton( this, NULL );
  1227. m_matViewButton -> move( 125,0 );
  1228. m_matViewButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "matview_active" ) );
  1229. m_matViewButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "matview_inactive" ) );
  1230. ToolTip::add( m_matViewButton, tr( "Matrix view" ) );
  1231. m_matViewButton -> setWhatsThis( tr( "The Matrix view contains the modulation matrix. Here you can define "
  1232. "the modulation relationships between the various operators: Each "
  1233. "audible operator (oscillators 1-3) has 3-4 properties that can be "
  1234. "modulated by any of the modulators. Using more modulations consumes "
  1235. "more CPU power. \n\n"
  1236. "The view is divided to modulation targets, grouped by the target oscillator. "
  1237. "Available targets are volume, pitch, phase, pulse width and sub-osc ratio. "
  1238. "Note: some targets are specific to one oscillator only. \n\n"
  1239. "Each modulation target has 4 knobs, one for each modulator. By default "
  1240. "the knobs are at 0, which means no modulation. Turning a knob to 1 causes "
  1241. "that modulator to affect the modulation target as much as possible. Turning "
  1242. "it to -1 does the same, but the modulation is inversed. " ) );
  1243. m_selectedViewGroup = new automatableButtonGroup( this );
  1244. m_selectedViewGroup -> addButton( m_opViewButton );
  1245. m_selectedViewGroup -> addButton( m_matViewButton );
  1246. connect( m_opViewButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
  1247. connect( m_matViewButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
  1248. }
  1249. MonstroView::~MonstroView()
  1250. {
  1251. }
  1252. void MonstroView::updateLayout()
  1253. {
  1254. switch( m_selectedViewGroup->model()->value() )
  1255. {
  1256. case OPVIEW:
  1257. m_operatorsView->show();
  1258. m_matrixView->hide();
  1259. break;
  1260. case MATVIEW:
  1261. m_operatorsView->hide();
  1262. m_matrixView->show();
  1263. break;
  1264. }
  1265. }
  1266. void MonstroView::modelChanged()
  1267. {
  1268. MonstroInstrument * m = castModel<MonstroInstrument>();
  1269. m_osc1VolKnob-> setModel( &m-> m_osc1Vol );
  1270. m_osc1PanKnob-> setModel( &m-> m_osc1Pan );
  1271. m_osc1CrsKnob-> setModel( &m-> m_osc1Crs );
  1272. m_osc1FtlKnob-> setModel( &m-> m_osc1Ftl );
  1273. m_osc1FtrKnob-> setModel( &m-> m_osc1Ftr );
  1274. m_osc1SpoKnob-> setModel( &m-> m_osc1Spo );
  1275. m_osc1PwKnob-> setModel( &m-> m_osc1Pw );
  1276. m_osc1SSRButton-> setModel( &m-> m_osc1SSR );
  1277. m_osc1SSFButton-> setModel( &m-> m_osc1SSF );
  1278. m_osc2VolKnob-> setModel( &m-> m_osc2Vol );
  1279. m_osc2PanKnob-> setModel( &m-> m_osc2Pan );
  1280. m_osc2CrsKnob-> setModel( &m-> m_osc2Crs );
  1281. m_osc2FtlKnob-> setModel( &m-> m_osc2Ftl );
  1282. m_osc2FtrKnob-> setModel( &m-> m_osc2Ftr );
  1283. m_osc2SpoKnob-> setModel( &m-> m_osc2Spo );
  1284. m_osc2WaveBox-> setModel( &m-> m_osc2Wave );
  1285. m_osc2SyncHButton-> setModel( &m-> m_osc2SyncH );
  1286. m_osc2SyncRButton-> setModel( &m-> m_osc2SyncR );
  1287. m_osc3VolKnob-> setModel( &m-> m_osc3Vol );
  1288. m_osc3PanKnob-> setModel( &m-> m_osc3Pan );
  1289. m_osc3CrsKnob-> setModel( &m-> m_osc3Crs );
  1290. m_osc3SpoKnob-> setModel( &m-> m_osc3Spo );
  1291. m_osc3SubKnob-> setModel( &m-> m_osc3Sub );
  1292. m_osc3Wave1Box-> setModel( &m-> m_osc3Wave1 );
  1293. m_osc3Wave2Box-> setModel( &m-> m_osc3Wave2 );
  1294. m_osc3SyncHButton-> setModel( &m-> m_osc3SyncH );
  1295. m_osc3SyncRButton-> setModel( &m-> m_osc3SyncR );
  1296. m_lfo1WaveBox-> setModel( &m-> m_lfo1Wave );
  1297. m_lfo1AttKnob-> setModel( &m-> m_lfo1Att );
  1298. m_lfo1RateKnob-> setModel( &m-> m_lfo1Rate );
  1299. m_lfo1PhsKnob-> setModel( &m-> m_lfo1Phs );
  1300. m_lfo2WaveBox-> setModel( &m-> m_lfo2Wave );
  1301. m_lfo2AttKnob-> setModel( &m-> m_lfo2Att );
  1302. m_lfo2RateKnob-> setModel( &m-> m_lfo2Rate );
  1303. m_lfo2PhsKnob-> setModel( &m-> m_lfo2Phs );
  1304. m_env1PreKnob-> setModel( &m-> m_env1Pre );
  1305. m_env1AttKnob-> setModel( &m-> m_env1Att );
  1306. m_env1HoldKnob-> setModel( &m-> m_env1Hold );
  1307. m_env1DecKnob-> setModel( &m-> m_env1Dec );
  1308. m_env1SusKnob-> setModel( &m-> m_env1Sus );
  1309. m_env1RelKnob-> setModel( &m-> m_env1Rel );
  1310. m_env1SlopeKnob-> setModel( &m-> m_env1Slope );
  1311. m_env2PreKnob-> setModel( &m-> m_env2Pre );
  1312. m_env2AttKnob-> setModel( &m-> m_env2Att );
  1313. m_env2HoldKnob-> setModel( &m-> m_env2Hold );
  1314. m_env2DecKnob-> setModel( &m-> m_env2Dec );
  1315. m_env2SusKnob-> setModel( &m-> m_env2Sus );
  1316. m_env2RelKnob-> setModel( &m-> m_env2Rel );
  1317. m_env2SlopeKnob-> setModel( &m-> m_env2Slope );
  1318. m_o23ModGroup-> setModel( &m-> m_o23Mod );
  1319. m_selectedViewGroup-> setModel( &m-> m_selectedView );
  1320. m_vol1env1Knob-> setModel( &m-> m_vol1env1 );
  1321. m_vol1env2Knob-> setModel( &m-> m_vol1env2 );
  1322. m_vol1lfo1Knob-> setModel( &m-> m_vol1lfo1 );
  1323. m_vol1lfo2Knob-> setModel( &m-> m_vol1lfo2 );
  1324. m_vol2env1Knob-> setModel( &m-> m_vol2env1 );
  1325. m_vol2env2Knob-> setModel( &m-> m_vol2env2 );
  1326. m_vol2lfo1Knob-> setModel( &m-> m_vol2lfo1 );
  1327. m_vol2lfo2Knob-> setModel( &m-> m_vol2lfo2 );
  1328. m_vol3env1Knob-> setModel( &m-> m_vol3env1 );
  1329. m_vol3env2Knob-> setModel( &m-> m_vol3env2 );
  1330. m_vol3lfo1Knob-> setModel( &m-> m_vol3lfo1 );
  1331. m_vol3lfo2Knob-> setModel( &m-> m_vol3lfo2 );
  1332. m_phs1env1Knob-> setModel( &m-> m_phs1env1 );
  1333. m_phs1env2Knob-> setModel( &m-> m_phs1env2 );
  1334. m_phs1lfo1Knob-> setModel( &m-> m_phs1lfo1 );
  1335. m_phs1lfo2Knob-> setModel( &m-> m_phs1lfo2 );
  1336. m_phs2env1Knob-> setModel( &m-> m_phs2env1 );
  1337. m_phs2env2Knob-> setModel( &m-> m_phs2env2 );
  1338. m_phs2lfo1Knob-> setModel( &m-> m_phs2lfo1 );
  1339. m_phs2lfo2Knob-> setModel( &m-> m_phs2lfo2 );
  1340. m_phs3env1Knob-> setModel( &m-> m_phs3env1 );
  1341. m_phs3env2Knob-> setModel( &m-> m_phs3env2 );
  1342. m_phs3lfo1Knob-> setModel( &m-> m_phs3lfo1 );
  1343. m_phs3lfo2Knob-> setModel( &m-> m_phs3lfo2 );
  1344. m_pit1env1Knob-> setModel( &m-> m_pit1env1 );
  1345. m_pit1env2Knob-> setModel( &m-> m_pit1env2 );
  1346. m_pit1lfo1Knob-> setModel( &m-> m_pit1lfo1 );
  1347. m_pit1lfo2Knob-> setModel( &m-> m_pit1lfo2 );
  1348. m_pit2env1Knob-> setModel( &m-> m_pit2env1 );
  1349. m_pit2env2Knob-> setModel( &m-> m_pit2env2 );
  1350. m_pit2lfo1Knob-> setModel( &m-> m_pit2lfo1 );
  1351. m_pit2lfo2Knob-> setModel( &m-> m_pit2lfo2 );
  1352. m_pit3env1Knob-> setModel( &m-> m_pit3env1 );
  1353. m_pit3env2Knob-> setModel( &m-> m_pit3env2 );
  1354. m_pit3lfo1Knob-> setModel( &m-> m_pit3lfo1 );
  1355. m_pit3lfo2Knob-> setModel( &m-> m_pit3lfo2 );
  1356. m_pw1env1Knob-> setModel( &m-> m_pw1env1 );
  1357. m_pw1env2Knob-> setModel( &m-> m_pw1env2 );
  1358. m_pw1lfo1Knob-> setModel( &m-> m_pw1lfo1 );
  1359. m_pw1lfo2Knob-> setModel( &m-> m_pw1lfo2 );
  1360. m_sub3env1Knob-> setModel( &m-> m_sub3env1 );
  1361. m_sub3env2Knob-> setModel( &m-> m_sub3env2 );
  1362. m_sub3lfo1Knob-> setModel( &m-> m_sub3lfo1 );
  1363. m_sub3lfo2Knob-> setModel( &m-> m_sub3lfo2 );
  1364. }
  1365. void MonstroView::setWidgetBackground( QWidget * _widget, const QString & _pic )
  1366. {
  1367. _widget->setAutoFillBackground( true );
  1368. QPalette pal;
  1369. pal.setBrush( _widget->backgroundRole(),
  1370. PLUGIN_NAME::getIconPixmap( _pic.toLatin1().constData() ) );
  1371. _widget->setPalette( pal );
  1372. }
  1373. QWidget * MonstroView::setupOperatorsView( QWidget * _parent )
  1374. {
  1375. // operators view
  1376. QWidget * view = new QWidget( _parent );
  1377. view-> setFixedSize( 250, 250 );
  1378. makeknob( m_osc1VolKnob, KNOBCOL1, O1ROW, tr( "Volume" ), "%", "osc1Knob" )
  1379. makeknob( m_osc1PanKnob, KNOBCOL2, O1ROW, tr( "Panning" ), "", "osc1Knob" )
  1380. makeknob( m_osc1CrsKnob, KNOBCOL3, O1ROW, tr( "Coarse detune" ), tr( " semitones" ), "osc1Knob" )
  1381. makeknob( m_osc1FtlKnob, KNOBCOL4, O1ROW, tr( "Finetune left" ), tr( " cents" ), "osc1Knob" )
  1382. makeknob( m_osc1FtrKnob, KNOBCOL5, O1ROW, tr( "Finetune right" ), tr( " cents" ), "osc1Knob" )
  1383. makeknob( m_osc1SpoKnob, KNOBCOL6, O1ROW, tr( "Stereo phase offset" ), tr( " deg" ), "osc1Knob" )
  1384. makeknob( m_osc1PwKnob, KNOBCOL7, O1ROW, tr( "Pulse width" ), "%", "osc1Knob" )
  1385. m_osc1VolKnob -> setVolumeKnob( true );
  1386. maketinyled( m_osc1SSRButton, 230, 34, tr( "Send sync on pulse rise" ) )
  1387. maketinyled( m_osc1SSFButton, 230, 44, tr( "Send sync on pulse fall" ) )
  1388. makeknob( m_osc2VolKnob, KNOBCOL1, O2ROW, tr( "Volume" ), "%", "osc2Knob" )
  1389. makeknob( m_osc2PanKnob, KNOBCOL2, O2ROW, tr( "Panning" ), "", "osc2Knob" )
  1390. makeknob( m_osc2CrsKnob, KNOBCOL3, O2ROW, tr( "Coarse detune" ), tr( " semitones" ), "osc2Knob" )
  1391. makeknob( m_osc2FtlKnob, KNOBCOL4, O2ROW, tr( "Finetune left" ), tr( " cents" ), "osc2Knob" )
  1392. makeknob( m_osc2FtrKnob, KNOBCOL5, O2ROW, tr( "Finetune right" ), tr( " cents" ), "osc2Knob" )
  1393. makeknob( m_osc2SpoKnob, KNOBCOL6, O2ROW, tr( "Stereo phase offset" ), tr( " deg" ), "osc2Knob" )
  1394. m_osc2VolKnob -> setVolumeKnob( true );
  1395. m_osc2WaveBox = new ComboBox( view );
  1396. m_osc2WaveBox -> setGeometry( 204, O2ROW + 7, 42, 22 );
  1397. m_osc2WaveBox->setFont( pointSize<8>( m_osc2WaveBox->font() ) );
  1398. maketinyled( m_osc2SyncHButton, 212, O2ROW - 3, tr( "Hard sync oscillator 2" ) )
  1399. maketinyled( m_osc2SyncRButton, 191, O2ROW - 3, tr( "Reverse sync oscillator 2" ) )
  1400. makeknob( m_osc3VolKnob, KNOBCOL1, O3ROW, tr( "Volume" ), "%", "osc3Knob" )
  1401. makeknob( m_osc3PanKnob, KNOBCOL2, O3ROW, tr( "Panning" ), "", "osc3Knob" )
  1402. makeknob( m_osc3CrsKnob, KNOBCOL3, O3ROW, tr( "Coarse detune" ), tr( " semitones" ), "osc3Knob" )
  1403. makeknob( m_osc3SpoKnob, KNOBCOL4, O3ROW, tr( "Stereo phase offset" ), tr( " deg" ), "osc3Knob" )
  1404. makeknob( m_osc3SubKnob, KNOBCOL5, O3ROW, tr( "Sub-osc mix" ), "", "osc3Knob" )
  1405. m_osc3VolKnob -> setVolumeKnob( true );
  1406. m_osc3Wave1Box = new ComboBox( view );
  1407. m_osc3Wave1Box -> setGeometry( 160, O3ROW + 7, 42, 22 );
  1408. m_osc3Wave1Box->setFont( pointSize<8>( m_osc3Wave1Box->font() ) );
  1409. m_osc3Wave2Box = new ComboBox( view );
  1410. m_osc3Wave2Box -> setGeometry( 204, O3ROW + 7, 42, 22 );
  1411. m_osc3Wave2Box->setFont( pointSize<8>( m_osc3Wave2Box->font() ) );
  1412. maketinyled( m_osc3SyncHButton, 212, O3ROW - 3, tr( "Hard sync oscillator 3" ) )
  1413. maketinyled( m_osc3SyncRButton, 191, O3ROW - 3, tr( "Reverse sync oscillator 3" ) )
  1414. m_lfo1WaveBox = new ComboBox( view );
  1415. m_lfo1WaveBox -> setGeometry( 2, LFOROW + 7, 42, 22 );
  1416. m_lfo1WaveBox->setFont( pointSize<8>( m_lfo1WaveBox->font() ) );
  1417. maketsknob( m_lfo1AttKnob, LFOCOL1, LFOROW, tr( "Attack" ), " ms", "lfoKnob" )
  1418. maketsknob( m_lfo1RateKnob, LFOCOL2, LFOROW, tr( "Rate" ), " ms", "lfoKnob" )
  1419. makeknob( m_lfo1PhsKnob, LFOCOL3, LFOROW, tr( "Phase" ), tr( " deg" ), "lfoKnob" )
  1420. m_lfo2WaveBox = new ComboBox( view );
  1421. m_lfo2WaveBox -> setGeometry( 127, LFOROW + 7, 42, 22 );
  1422. m_lfo2WaveBox->setFont( pointSize<8>( m_lfo2WaveBox->font() ) );
  1423. maketsknob( m_lfo2AttKnob, LFOCOL4, LFOROW, tr( "Attack" ), " ms", "lfoKnob" )
  1424. maketsknob( m_lfo2RateKnob, LFOCOL5, LFOROW, tr( "Rate" ), " ms", "lfoKnob" )
  1425. makeknob( m_lfo2PhsKnob, LFOCOL6, LFOROW, tr( "Phase" ), tr( " deg" ), "lfoKnob" )
  1426. maketsknob( m_env1PreKnob, KNOBCOL1, E1ROW, tr( "Pre-delay" ), " ms", "envKnob" )
  1427. maketsknob( m_env1AttKnob, KNOBCOL2, E1ROW, tr( "Attack" ), " ms", "envKnob" )
  1428. maketsknob( m_env1HoldKnob, KNOBCOL3, E1ROW, tr( "Hold" ), " ms", "envKnob" )
  1429. maketsknob( m_env1DecKnob, KNOBCOL4, E1ROW, tr( "Decay" ), " ms", "envKnob" )
  1430. makeknob( m_env1SusKnob, KNOBCOL5, E1ROW, tr( "Sustain" ), "", "envKnob" )
  1431. maketsknob( m_env1RelKnob, KNOBCOL6, E1ROW, tr( "Release" ), " ms", "envKnob" )
  1432. makeknob( m_env1SlopeKnob, KNOBCOL7, E1ROW, tr( "Slope" ), "", "envKnob" )
  1433. maketsknob( m_env2PreKnob, KNOBCOL1, E2ROW, tr( "Pre-delay" ), " ms", "envKnob" )
  1434. maketsknob( m_env2AttKnob, KNOBCOL2, E2ROW, tr( "Attack" ), " ms", "envKnob" )
  1435. maketsknob( m_env2HoldKnob, KNOBCOL3, E2ROW, tr( "Hold" ), " ms", "envKnob" )
  1436. maketsknob( m_env2DecKnob, KNOBCOL4, E2ROW, tr( "Decay" ), " ms", "envKnob" )
  1437. makeknob( m_env2SusKnob, KNOBCOL5, E2ROW, tr( "Sustain" ), "", "envKnob" )
  1438. maketsknob( m_env2RelKnob, KNOBCOL6, E2ROW, tr( "Release" ), " ms", "envKnob" )
  1439. makeknob( m_env2SlopeKnob, KNOBCOL7, E2ROW, tr( "Slope" ), "", "envKnob" )
  1440. // mod selector
  1441. PixmapButton * m_mixButton = new PixmapButton( view, NULL );
  1442. m_mixButton -> move( 225, 185 );
  1443. m_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_active" ) );
  1444. m_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "mix_inactive" ) );
  1445. ToolTip::add( m_mixButton, tr( "Mix Osc2 with Osc3" ) );
  1446. PixmapButton * m_amButton = new PixmapButton( view, NULL );
  1447. m_amButton -> move( 225, 185 + 15 );
  1448. m_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "am_active" ) );
  1449. m_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "am_inactive" ) );
  1450. ToolTip::add( m_amButton, tr( "Modulate amplitude of Osc3 with Osc2" ) );
  1451. PixmapButton * m_fmButton = new PixmapButton( view, NULL );
  1452. m_fmButton -> move( 225, 185 + 15*2 );
  1453. m_fmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_active" ) );
  1454. m_fmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "fm_inactive" ) );
  1455. ToolTip::add( m_fmButton, tr( "Modulate frequency of Osc3 with Osc2" ) );
  1456. PixmapButton * m_pmButton = new PixmapButton( view, NULL );
  1457. m_pmButton -> move( 225, 185 + 15*3 );
  1458. m_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_active" ) );
  1459. m_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "pm_inactive" ) );
  1460. ToolTip::add( m_pmButton, tr( "Modulate phase of Osc3 with Osc2" ) );
  1461. m_o23ModGroup = new automatableButtonGroup( view );
  1462. m_o23ModGroup-> addButton( m_mixButton );
  1463. m_o23ModGroup-> addButton( m_amButton );
  1464. m_o23ModGroup-> addButton( m_fmButton );
  1465. m_o23ModGroup-> addButton( m_pmButton );
  1466. ////////////////////////////////////
  1467. // //
  1468. // whatsthis-information strings //
  1469. // //
  1470. ////////////////////////////////////
  1471. m_osc1CrsKnob -> setWhatsThis( tr( "The CRS knob changes the tuning of oscillator 1 in semitone steps. " ) );
  1472. m_osc2CrsKnob -> setWhatsThis( tr( "The CRS knob changes the tuning of oscillator 2 in semitone steps. " ) );
  1473. m_osc3CrsKnob -> setWhatsThis( tr( "The CRS knob changes the tuning of oscillator 3 in semitone steps. " ) );
  1474. m_osc1FtlKnob -> setWhatsThis( tr( "FTL and FTR change the finetuning of the oscillator for left and right "
  1475. "channels respectively. These can add stereo-detuning to the oscillator "
  1476. "which widens the stereo image and causes an illusion of space. " ) );
  1477. m_osc1FtrKnob -> setWhatsThis( tr( "FTL and FTR change the finetuning of the oscillator for left and right "
  1478. "channels respectively. These can add stereo-detuning to the oscillator "
  1479. "which widens the stereo image and causes an illusion of space. " ) );
  1480. m_osc2FtlKnob -> setWhatsThis( tr( "FTL and FTR change the finetuning of the oscillator for left and right "
  1481. "channels respectively. These can add stereo-detuning to the oscillator "
  1482. "which widens the stereo image and causes an illusion of space. " ) );
  1483. m_osc2FtrKnob -> setWhatsThis( tr( "FTL and FTR change the finetuning of the oscillator for left and right "
  1484. "channels respectively. These can add stereo-detuning to the oscillator "
  1485. "which widens the stereo image and causes an illusion of space. " ) );
  1486. m_osc1SpoKnob -> setWhatsThis( tr( "The SPO knob modifies the difference in phase between left and right "
  1487. "channels. Higher difference creates a wider stereo image. " ) );
  1488. m_osc2SpoKnob -> setWhatsThis( tr( "The SPO knob modifies the difference in phase between left and right "
  1489. "channels. Higher difference creates a wider stereo image. " ) );
  1490. m_osc3SpoKnob -> setWhatsThis( tr( "The SPO knob modifies the difference in phase between left and right "
  1491. "channels. Higher difference creates a wider stereo image. " ) );
  1492. m_osc1PwKnob -> setWhatsThis( tr( "The PW knob controls the pulse width, also known as duty cycle, "
  1493. "of oscillator 1. Oscillator 1 is a digital pulse wave oscillator, "
  1494. "it doesn't produce bandlimited output, which means that you can "
  1495. "use it as an audible oscillator but it will cause aliasing. You can "
  1496. "also use it as an inaudible source of a sync signal, which can be "
  1497. "used to synchronize oscillators 2 and 3. " ) );
  1498. m_osc1SSRButton -> setWhatsThis( tr( "Send Sync on Rise: When enabled, the Sync signal is sent every time "
  1499. "the state of oscillator 1 changes from low to high, ie. when the amplitude "
  1500. "changes from -1 to 1. "
  1501. "Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, "
  1502. "but its volume has no effect on them. Sync signals are sent independently "
  1503. "for both left and right channels. " ) );
  1504. m_osc1SSFButton -> setWhatsThis( tr( "Send Sync on Fall: When enabled, the Sync signal is sent every time "
  1505. "the state of oscillator 1 changes from high to low, ie. when the amplitude "
  1506. "changes from 1 to -1. "
  1507. "Oscillator 1's pitch, phase and pulse width may affect the timing of syncs, "
  1508. "but its volume has no effect on them. Sync signals are sent independently "
  1509. "for both left and right channels. " ) );
  1510. m_osc2SyncHButton -> setWhatsThis( tr( "Hard sync: Every time the oscillator receives a sync signal from oscillator 1, "
  1511. "its phase is reset to 0 + whatever its phase offset is. " ) );
  1512. m_osc3SyncHButton -> setWhatsThis( tr( "Hard sync: Every time the oscillator receives a sync signal from oscillator 1, "
  1513. "its phase is reset to 0 + whatever its phase offset is. " ) );
  1514. m_osc2SyncRButton -> setWhatsThis( tr( "Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, "
  1515. "the amplitude of the oscillator gets inverted. " ) );
  1516. m_osc3SyncRButton -> setWhatsThis( tr( "Reverse sync: Every time the oscillator receives a sync signal from oscillator 1, "
  1517. "the amplitude of the oscillator gets inverted. " ) );
  1518. m_osc2WaveBox -> setWhatsThis( tr( "Choose waveform for oscillator 2. " ) );
  1519. m_osc3Wave1Box -> setWhatsThis( tr( "Choose waveform for oscillator 3's first sub-osc. "
  1520. "Oscillator 3 can smoothly interpolate between two different waveforms. " ) );
  1521. m_osc3Wave2Box -> setWhatsThis( tr( "Choose waveform for oscillator 3's second sub-osc. "
  1522. "Oscillator 3 can smoothly interpolate between two different waveforms. " ) );
  1523. m_osc3SubKnob -> setWhatsThis( tr( "The SUB knob changes the mixing ratio of the two sub-oscs of oscillator 3. "
  1524. "Each sub-osc can be set to produce a different waveform, and oscillator 3 "
  1525. "can smoothly interpolate between them. All incoming modulations to oscillator 3 are applied "
  1526. "to both sub-oscs/waveforms in the exact same way. " ) );
  1527. m_mixButton -> setWhatsThis( tr( "In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by "
  1528. "the output of oscillator 2. \n\n"
  1529. "Mix mode means no modulation: the outputs of the oscillators are simply mixed together. " ) );
  1530. m_amButton -> setWhatsThis( tr( "In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by "
  1531. "the output of oscillator 2. \n\n"
  1532. "AM means amplitude modulation: Oscillator 3's amplitude (volume) is modulated by oscillator 2. " ) );
  1533. m_fmButton -> setWhatsThis( tr( "In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by "
  1534. "the output of oscillator 2. \n\n"
  1535. "FM means frequency modulation: Oscillator 3's frequency (pitch) is modulated by oscillator 2. "
  1536. "The frequency modulation is implemented as phase modulation, which gives a more stable overall pitch "
  1537. "than \"pure\" frequency modulation. " ) );
  1538. m_pmButton -> setWhatsThis( tr( "In addition to dedicated modulators, Monstro allows oscillator 3 to be modulated by "
  1539. "the output of oscillator 2. \n\n"
  1540. "PM means phase modulation: Oscillator 3's phase is modulated by oscillator 2. "
  1541. "It differs from frequency modulation in that the phase changes are not cumulative. " ) );
  1542. m_lfo1WaveBox -> setWhatsThis( tr( "Select the waveform for LFO 1. \n"
  1543. "\"Random\" and \"Random smooth\" are special waveforms: "
  1544. "they produce random output, where the rate of the LFO controls how often "
  1545. "the state of the LFO changes. The smooth version interpolates between these "
  1546. "states with cosine interpolation. These random modes can be used to give "
  1547. "\"life\" to your presets - add some of that analog unpredictability... " ) );
  1548. m_lfo2WaveBox -> setWhatsThis( tr( "Select the waveform for LFO 2. \n"
  1549. "\"Random\" and \"Random smooth\" are special waveforms: "
  1550. "they produce random output, where the rate of the LFO controls how often "
  1551. "the state of the LFO changes. The smooth version interpolates between these "
  1552. "states with cosine interpolation. These random modes can be used to give "
  1553. "\"life\" to your presets - add some of that analog unpredictability... " ) );
  1554. m_lfo1AttKnob -> setWhatsThis( tr( "Attack causes the LFO to come on gradually from the start of the note. " ) );
  1555. m_lfo2AttKnob -> setWhatsThis( tr( "Attack causes the LFO to come on gradually from the start of the note. " ) );
  1556. m_lfo1RateKnob -> setWhatsThis( tr( "Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. " ) );
  1557. m_lfo2RateKnob -> setWhatsThis( tr( "Rate sets the speed of the LFO, measured in milliseconds per cycle. Can be synced to tempo. " ) );
  1558. m_lfo1PhsKnob -> setWhatsThis( tr( "PHS controls the phase offset of the LFO. " ) );
  1559. m_lfo2PhsKnob -> setWhatsThis( tr( "PHS controls the phase offset of the LFO. " ) );
  1560. m_env1PreKnob -> setWhatsThis( tr( "PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. " ) );
  1561. m_env2PreKnob -> setWhatsThis( tr( "PRE, or pre-delay, delays the start of the envelope from the start of the note. 0 means no delay. " ) );
  1562. m_env1AttKnob -> setWhatsThis( tr( "ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. "
  1563. "A value of 0 means instant. " ) );
  1564. m_env2AttKnob -> setWhatsThis( tr( "ATT, or attack, controls how fast the envelope ramps up at start, measured in milliseconds. "
  1565. "A value of 0 means instant. " ) );
  1566. m_env1HoldKnob -> setWhatsThis( tr( "HOLD controls how long the envelope stays at peak after the attack phase. " ) );
  1567. m_env2HoldKnob -> setWhatsThis( tr( "HOLD controls how long the envelope stays at peak after the attack phase. " ) );
  1568. m_env1DecKnob -> setWhatsThis( tr( "DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds "
  1569. "it would take to go from peak to zero. The actual decay may be shorter if sustain is used. ") );
  1570. m_env2DecKnob -> setWhatsThis( tr( "DEC, or decay, controls how fast the envelope falls off from its peak, measured in milliseconds "
  1571. "it would take to go from peak to zero. The actual decay may be shorter if sustain is used. ") );
  1572. m_env1SusKnob -> setWhatsThis( tr( "SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level "
  1573. "as long as the note is held. " ) );
  1574. m_env2SusKnob -> setWhatsThis( tr( "SUS, or sustain, controls the sustain level of the envelope. The decay phase will not go below this level "
  1575. "as long as the note is held. " ) );
  1576. m_env1RelKnob -> setWhatsThis( tr( "REL, or release, controls how long the release is for the note, measured in how long it would take to "
  1577. "fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. ") );
  1578. m_env2RelKnob -> setWhatsThis( tr( "REL, or release, controls how long the release is for the note, measured in how long it would take to "
  1579. "fall from peak to zero. Actual release may be shorter, depending on at what phase the note is released. ") );
  1580. m_env1SlopeKnob -> setWhatsThis( tr( "The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. "
  1581. "Negative values create curves that start slowly, peak quickly and fall of slowly again. "
  1582. "Positive values create curves that start and end quickly, and stay longer near the peaks. " ) );
  1583. m_env2SlopeKnob -> setWhatsThis( tr( "The slope knob controls the curve or shape of the envelope. A value of 0 creates straight rises and falls. "
  1584. "Negative values create curves that start slowly, peak quickly and fall of slowly again. "
  1585. "Positive values create curves that start and end quickly, and stay longer near the peaks. " ) );
  1586. return( view );
  1587. }
  1588. QWidget * MonstroView::setupMatrixView( QWidget * _parent )
  1589. {
  1590. // matrix view
  1591. QWidget * view = new QWidget( _parent );
  1592. view-> setFixedSize( 250, 250 );
  1593. makeknob( m_vol1env1Knob, MATCOL1, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1594. makeknob( m_vol1env2Knob, MATCOL2, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1595. makeknob( m_vol1lfo1Knob, MATCOL3, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1596. makeknob( m_vol1lfo2Knob, MATCOL4, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1597. makeknob( m_vol2env1Knob, MATCOL1, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1598. makeknob( m_vol2env2Knob, MATCOL2, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1599. makeknob( m_vol2lfo1Knob, MATCOL3, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1600. makeknob( m_vol2lfo2Knob, MATCOL4, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1601. makeknob( m_vol3env1Knob, MATCOL1, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1602. makeknob( m_vol3env2Knob, MATCOL2, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1603. makeknob( m_vol3lfo1Knob, MATCOL3, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1604. makeknob( m_vol3lfo2Knob, MATCOL4, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1605. makeknob( m_phs1env1Knob, MATCOL1, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1606. makeknob( m_phs1env2Knob, MATCOL2, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1607. makeknob( m_phs1lfo1Knob, MATCOL3, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1608. makeknob( m_phs1lfo2Knob, MATCOL4, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1609. makeknob( m_phs2env1Knob, MATCOL1, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" )
  1610. makeknob( m_phs2env2Knob, MATCOL2, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" )
  1611. makeknob( m_phs2lfo1Knob, MATCOL3, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" )
  1612. makeknob( m_phs2lfo2Knob, MATCOL4, MATROW4, tr( "Modulation amount" ), "", "matrixKnob" )
  1613. makeknob( m_phs3env1Knob, MATCOL1, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1614. makeknob( m_phs3env2Knob, MATCOL2, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1615. makeknob( m_phs3lfo1Knob, MATCOL3, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1616. makeknob( m_phs3lfo2Knob, MATCOL4, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1617. makeknob( m_pit1env1Knob, MATCOL5, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1618. makeknob( m_pit1env2Knob, MATCOL6, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1619. makeknob( m_pit1lfo1Knob, MATCOL7, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1620. makeknob( m_pit1lfo2Knob, MATCOL8, MATROW1, tr( "Modulation amount" ), "", "matrixKnob" )
  1621. makeknob( m_pit2env1Knob, MATCOL5, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1622. makeknob( m_pit2env2Knob, MATCOL6, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1623. makeknob( m_pit2lfo1Knob, MATCOL7, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1624. makeknob( m_pit2lfo2Knob, MATCOL8, MATROW3, tr( "Modulation amount" ), "", "matrixKnob" )
  1625. makeknob( m_pit3env1Knob, MATCOL5, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1626. makeknob( m_pit3env2Knob, MATCOL6, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1627. makeknob( m_pit3lfo1Knob, MATCOL7, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1628. makeknob( m_pit3lfo2Knob, MATCOL8, MATROW5, tr( "Modulation amount" ), "", "matrixKnob" )
  1629. makeknob( m_pw1env1Knob, MATCOL5, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1630. makeknob( m_pw1env2Knob, MATCOL6, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1631. makeknob( m_pw1lfo1Knob, MATCOL7, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1632. makeknob( m_pw1lfo2Knob, MATCOL8, MATROW2, tr( "Modulation amount" ), "", "matrixKnob" )
  1633. makeknob( m_sub3env1Knob, MATCOL5, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1634. makeknob( m_sub3env2Knob, MATCOL6, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1635. makeknob( m_sub3lfo1Knob, MATCOL7, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1636. makeknob( m_sub3lfo2Knob, MATCOL8, MATROW6, tr( "Modulation amount" ), "", "matrixKnob" )
  1637. return( view );
  1638. }
  1639. extern "C"
  1640. {
  1641. // necessary for getting instance out of shared lib
  1642. Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data )
  1643. {
  1644. return new MonstroInstrument( static_cast<InstrumentTrack *>( _data ) );
  1645. }
  1646. }