Nes.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. /* Nes.cpp - A NES instrument plugin for LMMS
  2. *
  3. * Copyright (c) 2014 Vesa Kivimäki
  4. * Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
  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 "Nes.h"
  26. #include "Engine.h"
  27. #include "InstrumentTrack.h"
  28. #include "ToolTip.h"
  29. #include "Song.h"
  30. #include "lmms_math.h"
  31. #include "interpolation.h"
  32. #include "Mixer.h"
  33. #include "Oscillator.h"
  34. #include "embed.h"
  35. #include "plugin_export.h"
  36. extern "C"
  37. {
  38. Plugin::Descriptor PLUGIN_EXPORT nes_plugin_descriptor =
  39. {
  40. STRINGIFY( PLUGIN_NAME ),
  41. "Nescaline",
  42. QT_TRANSLATE_NOOP( "pluginBrowser",
  43. "A NES-like synthesizer" ),
  44. "Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
  45. 0x0100,
  46. Plugin::Instrument,
  47. new PluginPixmapLoader( "logo" ),
  48. NULL,
  49. NULL
  50. } ;
  51. }
  52. NesObject::NesObject( NesInstrument * nes, const sample_rate_t samplerate, NotePlayHandle * nph ) :
  53. m_parent( nes ),
  54. m_samplerate( samplerate ),
  55. m_nph( nph )
  56. {
  57. m_pitchUpdateCounter = 0;
  58. m_pitchUpdateFreq = wavelength( 60.0f );
  59. m_LFSR = LFSR_INIT;
  60. m_ch1Counter = 0;
  61. m_ch2Counter = 0;
  62. m_ch3Counter = 0;
  63. m_ch4Counter = 0;
  64. m_ch1EnvCounter = 0;
  65. m_ch2EnvCounter = 0;
  66. m_ch4EnvCounter = 0;
  67. m_ch1EnvValue = 15;
  68. m_ch2EnvValue = 15;
  69. m_ch4EnvValue = 15;
  70. m_ch1SweepCounter = 0;
  71. m_ch2SweepCounter = 0;
  72. m_ch4SweepCounter = 0;
  73. m_12Last = 0.0f;
  74. m_34Last = 0.0f;
  75. m_maxWlen = wavelength( MIN_FREQ );
  76. m_nsf = NES_SIMPLE_FILTER * ( m_samplerate / 44100.0 );
  77. m_lastNoteFreq = 0;
  78. m_lastNoiseFreq = -1.0f; // value that is always different than noisefreq so it gets updated at start
  79. m_vibratoPhase = 0;
  80. updatePitch();
  81. }
  82. NesObject::~NesObject()
  83. {
  84. }
  85. void NesObject::renderOutput( sampleFrame * buf, fpp_t frames )
  86. {
  87. ////////////////////////////////
  88. // //
  89. // variables for processing //
  90. // //
  91. ////////////////////////////////
  92. bool ch1Enabled = m_parent->m_ch1Enabled.value();
  93. bool ch2Enabled = m_parent->m_ch2Enabled.value();
  94. bool ch3Enabled = m_parent->m_ch3Enabled.value();
  95. bool ch4Enabled = m_parent->m_ch4Enabled.value();
  96. float ch1DutyCycle = DUTY_CYCLE[ m_parent->m_ch1DutyCycle.value() ];
  97. int ch1EnvLen = wavelength( floorf( 240.0 / ( m_parent->m_ch1EnvLen.value() + 1 ) ) );
  98. bool ch1EnvLoop = m_parent->m_ch1EnvLooped.value();
  99. float ch2DutyCycle = DUTY_CYCLE[ m_parent->m_ch2DutyCycle.value() ];
  100. int ch2EnvLen = wavelength( floorf( 240.0 / ( m_parent->m_ch2EnvLen.value() + 1 ) ) );
  101. bool ch2EnvLoop = m_parent->m_ch2EnvLooped.value();
  102. int ch4EnvLen = wavelength( floorf( 240.0 / ( m_parent->m_ch4EnvLen.value() + 1 ) ) );
  103. bool ch4EnvLoop = m_parent->m_ch4EnvLooped.value();
  104. // processing variables for operators
  105. int ch1;
  106. int ch2;
  107. int ch3;
  108. int ch4;
  109. // levels for generators (used for dc offset compensation)
  110. int ch1Level;
  111. int ch2Level;
  112. int ch3Level;
  113. int ch4Level;
  114. int ch1SweepRate = wavelength( floorf( 120.0 / ( m_parent->m_ch1SweepRate.value() + 1 ) ) );
  115. int ch2SweepRate = wavelength( floorf( 120.0 / ( m_parent->m_ch2SweepRate.value() + 1 ) ) );
  116. int ch4SweepRate = wavelength( floorf( 60.0f / ( 8.0f - qAbs( m_parent->m_ch4Sweep.value() ) ) ) );
  117. int ch1Sweep = static_cast<int>( m_parent->m_ch1SweepAmt.value() * -1.0 );
  118. int ch2Sweep = static_cast<int>( m_parent->m_ch2SweepAmt.value() * -1.0 );
  119. int ch4Sweep = 0;
  120. if( m_parent->m_ch4Sweep.value() != 0.0f )
  121. {
  122. ch4Sweep = m_parent->m_ch4Sweep.value() > 0.0f
  123. ? -1
  124. : 1;
  125. }
  126. // the amounts are inverted so we correct them here
  127. if( ch1Sweep > 0 )
  128. {
  129. ch1Sweep = 8 - ch1Sweep;
  130. }
  131. if( ch1Sweep < 0 )
  132. {
  133. ch1Sweep = -8 - ch1Sweep;
  134. }
  135. if( ch2Sweep > 0 )
  136. {
  137. ch2Sweep = 8 - ch2Sweep;
  138. }
  139. if( ch2Sweep < 0 )
  140. {
  141. ch2Sweep = -8 - ch2Sweep;
  142. }
  143. // start framebuffer loop
  144. for( f_cnt_t f = 0; f < frames; f++ )
  145. {
  146. ////////////////////////////////
  147. // //
  148. // pitch update //
  149. // //
  150. ////////////////////////////////
  151. m_pitchUpdateCounter++;
  152. if( m_pitchUpdateCounter >= m_pitchUpdateFreq )
  153. {
  154. updatePitch();
  155. m_pitchUpdateCounter = 0;
  156. }
  157. ////////////////////////////////
  158. // //
  159. // channel 1 //
  160. // //
  161. ////////////////////////////////
  162. // render pulse wave
  163. if( m_wlen1 <= m_maxWlen && m_wlen1 >= MIN_WLEN && ch1Enabled )
  164. {
  165. ch1Level = m_parent->m_ch1EnvEnabled.value()
  166. ? static_cast<int>( ( m_parent->m_ch1Volume.value() * m_ch1EnvValue ) / 15.0 )
  167. : static_cast<int>( m_parent->m_ch1Volume.value() );
  168. ch1 = m_ch1Counter > m_wlen1 * ch1DutyCycle
  169. ? 0
  170. : ch1Level;
  171. }
  172. else ch1 = ch1Level = 0;
  173. // update sweep
  174. m_ch1SweepCounter++;
  175. if( m_ch1SweepCounter >= ch1SweepRate )
  176. {
  177. m_ch1SweepCounter = 0;
  178. if( m_parent->m_ch1SweepEnabled.value() && m_wlen1 <= m_maxWlen && m_wlen1 >= MIN_WLEN )
  179. {
  180. // check if the sweep goes up or down
  181. if( ch1Sweep > 0 )
  182. {
  183. m_wlen1 += m_wlen1 >> qAbs( ch1Sweep );
  184. }
  185. if( ch1Sweep < 0 )
  186. {
  187. m_wlen1 -= m_wlen1 >> qAbs( ch1Sweep );
  188. m_wlen1--; // additional minus 1 for ch1 only
  189. }
  190. }
  191. }
  192. // update framecounters
  193. m_ch1Counter++;
  194. m_ch1Counter = m_wlen1 ? m_ch1Counter % m_wlen1 : 0;
  195. m_ch1EnvCounter++;
  196. if( m_ch1EnvCounter >= ch1EnvLen )
  197. {
  198. m_ch1EnvCounter = 0;
  199. m_ch1EnvValue--;
  200. if( m_ch1EnvValue < 0 )
  201. {
  202. m_ch1EnvValue = ch1EnvLoop ? 15 : 0;
  203. }
  204. }
  205. ////////////////////////////////
  206. // //
  207. // channel 2 //
  208. // //
  209. ////////////////////////////////
  210. // render pulse wave
  211. if( m_wlen2 <= m_maxWlen && m_wlen2 >= MIN_WLEN && ch2Enabled )
  212. {
  213. ch2Level = m_parent->m_ch2EnvEnabled.value()
  214. ? static_cast<int>( ( m_parent->m_ch2Volume.value() * m_ch2EnvValue ) / 15.0 )
  215. : static_cast<int>( m_parent->m_ch2Volume.value() );
  216. ch2 = m_ch2Counter > m_wlen2 * ch2DutyCycle
  217. ? 0
  218. : ch2Level;
  219. }
  220. else ch2 = ch2Level = 0;
  221. // update sweep
  222. m_ch2SweepCounter++;
  223. if( m_ch2SweepCounter >= ch2SweepRate )
  224. {
  225. m_ch2SweepCounter = 0;
  226. if( m_parent->m_ch2SweepEnabled.value() && m_wlen2 <= m_maxWlen && m_wlen2 >= MIN_WLEN )
  227. {
  228. // check if the sweep goes up or down
  229. if( ch2Sweep > 0 )
  230. {
  231. m_wlen2 += m_wlen2 >> qAbs( ch2Sweep );
  232. }
  233. if( ch2Sweep < 0 )
  234. {
  235. m_wlen2 -= m_wlen2 >> qAbs( ch2Sweep );
  236. }
  237. }
  238. }
  239. // update framecounters
  240. m_ch2Counter++;
  241. m_ch2Counter = m_wlen2 ? m_ch2Counter % m_wlen2 : 0;
  242. m_ch2EnvCounter++;
  243. if( m_ch2EnvCounter >= ch2EnvLen )
  244. {
  245. m_ch2EnvCounter = 0;
  246. m_ch2EnvValue--;
  247. if( m_ch2EnvValue < 0 )
  248. {
  249. m_ch2EnvValue = ch2EnvLoop
  250. ? 15
  251. : 0;
  252. }
  253. }
  254. ////////////////////////////////
  255. // //
  256. // channel 3 //
  257. // //
  258. ////////////////////////////////
  259. // make sure we don't overflow
  260. m_ch3Counter = m_wlen3 ? m_ch3Counter % m_wlen3 : 0;
  261. // render triangle wave
  262. if( m_wlen3 <= m_maxWlen && ch3Enabled )
  263. {
  264. ch3Level = static_cast<int>( m_parent->m_ch3Volume.value() );
  265. ch3 = m_wlen3 ? TRIANGLE_WAVETABLE[ ( m_ch3Counter * 32 ) / m_wlen3 ] : 0;
  266. ch3 = ( ch3 * ch3Level ) / 15;
  267. }
  268. else ch3 = ch3Level = 0;
  269. m_ch3Counter++;
  270. ////////////////////////////////
  271. // //
  272. // channel 4 //
  273. // //
  274. ////////////////////////////////
  275. // render pseudo noise
  276. if( ch4Enabled )
  277. {
  278. ch4Level = m_parent->m_ch4EnvEnabled.value()
  279. ? ( static_cast<int>( m_parent->m_ch4Volume.value() ) * m_ch4EnvValue ) / 15
  280. : static_cast<int>( m_parent->m_ch4Volume.value() );
  281. ch4 = LFSR()
  282. ? ch4Level
  283. : 0;
  284. }
  285. else ch4 = ch4Level = 0;
  286. // update framecounters
  287. m_ch4Counter++;
  288. if( m_ch4Counter >= m_wlen4 )
  289. {
  290. m_ch4Counter = 0;
  291. updateLFSR( m_parent->m_ch4NoiseMode.value() );
  292. }
  293. m_ch4EnvCounter++;
  294. if( m_ch4EnvCounter >= ch4EnvLen )
  295. {
  296. m_ch4EnvCounter = 0;
  297. m_ch4EnvValue--;
  298. if( m_ch4EnvValue < 0 )
  299. {
  300. m_ch4EnvValue = ch4EnvLoop
  301. ? 15
  302. : 0;
  303. }
  304. }
  305. m_ch4SweepCounter++;
  306. if( m_ch4SweepCounter >= ch4SweepRate )
  307. {
  308. m_ch4SweepCounter = 0;
  309. if( ch4Sweep != 0 )
  310. {
  311. int freqN = nearestNoiseFreq( static_cast<float>( m_samplerate ) / m_wlen4 );
  312. freqN = qBound( 0, freqN + ch4Sweep, 15 );
  313. m_wlen4 = wavelength( NOISE_FREQS[ freqN ] );
  314. if( m_wlen4 == 0 && ch4Sweep == 1 ) // a workaround for sweep getting stuck on 0 wavelength
  315. {
  316. while( m_wlen4 == 0 )
  317. {
  318. m_wlen4 = wavelength( NOISE_FREQS[ ++freqN ] );
  319. }
  320. }
  321. }
  322. }
  323. ////////////////////////////////
  324. // //
  325. // final stage - mixing //
  326. // //
  327. ////////////////////////////////
  328. float pin1 = static_cast<float>( ch1 + ch2 );
  329. // add dithering noise
  330. pin1 *= 1.0 + ( Oscillator::noiseSample( 0.0f ) * DITHER_AMP );
  331. pin1 = pin1 / 30.0f;
  332. pin1 = signedPow( pin1, NES_DIST );
  333. pin1 = pin1 * 2.0f - 1.0f;
  334. // simple first order iir filter, to simulate the frequency response falloff in nes analog audio output
  335. pin1 = linearInterpolate( pin1, m_12Last, m_nsf );
  336. m_12Last = pin1;
  337. // compensate DC offset
  338. pin1 += 1.0f - signedPow( static_cast<float>( ch1Level + ch2Level ) / 30.0f, NES_DIST );
  339. pin1 *= NES_MIXING_12;
  340. float pin2 = static_cast<float>( ch3 + ch4 );
  341. // add dithering noise
  342. pin2 *= 1.0 + ( Oscillator::noiseSample( 0.0f ) * DITHER_AMP );
  343. pin2 = pin2 / 30.0f;
  344. pin2 = signedPow( pin2, NES_DIST );
  345. pin2 = pin2 * 2.0f - 1.0f;
  346. // simple first order iir filter, to simulate the frequency response falloff in nes analog audio output
  347. pin2 = linearInterpolate( pin2, m_34Last, m_nsf );
  348. m_34Last = pin2;
  349. // compensate DC offset
  350. pin2 += 1.0f - signedPow( static_cast<float>( ch3Level + ch4Level ) / 30.0f, NES_DIST );
  351. pin2 *= NES_MIXING_34;
  352. const float mixdown = ( pin1 + pin2 ) * NES_MIXING_ALL * m_parent->m_masterVol.value();
  353. buf[f][0] = mixdown;
  354. buf[f][1] = mixdown;
  355. } // end framebuffer loop
  356. }
  357. void NesObject::updateVibrato( float * freq )
  358. {
  359. float vibratoAmt = floorf( m_parent->m_vibrato.value() ) / 15.0f;
  360. m_vibratoPhase++;
  361. m_vibratoPhase %= 32;
  362. float vibratoRatio = 1.0f + ( static_cast<float>( TRIANGLE_WAVETABLE[ m_vibratoPhase ] ) * 0.02f * vibratoAmt );
  363. *freq *= vibratoRatio;
  364. }
  365. void NesObject::updatePitch()
  366. {
  367. float freq = m_nph->frequency();
  368. // if vibrato is active, update vibrato
  369. if( m_parent->m_vibrato.value() > 0 )
  370. {
  371. updateVibrato( &freq );
  372. }
  373. // check if frequency has changed, if so, update wavelengths of ch1-3
  374. if( freq != m_lastNoteFreq )
  375. {
  376. m_wlen1 = wavelength( freq * m_parent->m_freq1 );
  377. m_wlen2 = wavelength( freq * m_parent->m_freq2 );
  378. m_wlen3 = wavelength( freq * m_parent->m_freq3 );
  379. }
  380. // noise channel can use either note freq or preset freqs
  381. if( m_parent->m_ch4NoiseFreqMode.value() && freq != m_lastNoteFreq )
  382. {
  383. float f = freq * 2.0f;
  384. if( m_parent->m_ch4NoiseQuantize.value() ) // note freq can be quantized to the preset freqs
  385. {
  386. f = NOISE_FREQS[ nearestNoiseFreq( f ) ];
  387. }
  388. m_wlen4 = wavelength( f );
  389. }
  390. if( ! m_parent->m_ch4NoiseFreqMode.value() && m_lastNoiseFreq != m_parent->m_ch4NoiseFreq.value() )
  391. {
  392. m_wlen4 = wavelength( NOISE_FREQS[ 15 - static_cast<int>( m_parent->m_ch4NoiseFreq.value() ) ] );
  393. m_lastNoiseFreq = m_parent->m_ch4NoiseFreq.value();
  394. }
  395. m_lastNoteFreq = freq;
  396. }
  397. NesInstrument::NesInstrument( InstrumentTrack * instrumentTrack ) :
  398. Instrument( instrumentTrack, &nes_plugin_descriptor ),
  399. m_ch1Enabled( true, this ),
  400. m_ch1Crs( 0.f, -24.f, 24.f, 1.f, this, tr( "Channel 1 coarse detune" ) ),
  401. m_ch1Volume( 15.f, 0.f, 15.f, 1.f, this, tr( "Channel 1 volume" ) ),
  402. m_ch1EnvEnabled( false, this ),
  403. m_ch1EnvLooped( false, this ),
  404. m_ch1EnvLen( 0.f, 0.f, 15.f, 1.f, this, tr( "Channel 1 envelope length" ) ),
  405. m_ch1DutyCycle( 0, 0, 3, this, tr( "Channel 1 duty cycle" ) ),
  406. m_ch1SweepEnabled( false, this ),
  407. m_ch1SweepAmt( 0.f, -7.f, 7.f, 1.f, this, tr( "Channel 1 sweep amount" ) ),
  408. m_ch1SweepRate( 0.f, 0.f, 7.f, 1.f, this, tr( "Channel 1 sweep rate" ) ),
  409. m_ch2Enabled( true, this ),
  410. m_ch2Crs( 0.f, -24.f, 24.f, 1.f, this, tr( "Channel 2 Coarse detune" ) ),
  411. m_ch2Volume( 15.f, 0.f, 15.f, 1.f, this, tr( "Channel 2 Volume" ) ),
  412. m_ch2EnvEnabled( false, this ),
  413. m_ch2EnvLooped( false, this ),
  414. m_ch2EnvLen( 0.f, 0.f, 15.f, 1.f, this, tr( "Channel 2 envelope length" ) ),
  415. m_ch2DutyCycle( 2, 0, 3, this, tr( "Channel 2 duty cycle" ) ),
  416. m_ch2SweepEnabled( false, this ),
  417. m_ch2SweepAmt( 0.f, -7.f, 7.f, 1.f, this, tr( "Channel 2 sweep amount" ) ),
  418. m_ch2SweepRate( 0.f, 0.f, 7.f, 1.f, this, tr( "Channel 2 sweep rate" ) ),
  419. //channel 3
  420. m_ch3Enabled( true, this ),
  421. m_ch3Crs( 0.f, -24.f, 24.f, 1.f, this, tr( "Channel 3 coarse detune" ) ),
  422. m_ch3Volume( 15.f, 0.f, 15.f, 1.f, this, tr( "Channel 3 volume" ) ),
  423. //channel 4
  424. m_ch4Enabled( false, this ),
  425. m_ch4Volume( 15.f, 0.f, 15.f, 1.f, this, tr( "Channel 4 volume" ) ),
  426. m_ch4EnvEnabled( false, this ),
  427. m_ch4EnvLooped( false, this ),
  428. m_ch4EnvLen( 0.f, 0.f, 15.f, 1.f, this, tr( "Channel 4 envelope length" ) ),
  429. m_ch4NoiseMode( false, this ),
  430. m_ch4NoiseFreqMode( false, this ),
  431. m_ch4NoiseFreq( 0.f, 0.f, 15.f, 1.f, this, tr( "Channel 4 noise frequency" ) ),
  432. m_ch4Sweep( 0.f, -7.f, 7.f, 1.f, this, tr( "Channel 4 noise frequency sweep" ) ),
  433. m_ch4NoiseQuantize( true, this ),
  434. //master
  435. m_masterVol( 1.0f, 0.0f, 2.0f, 0.01f, this, tr( "Master volume" ) ),
  436. m_vibrato( 0.0f, 0.0f, 15.0f, 1.0f, this, tr( "Vibrato" ) )
  437. {
  438. connect( &m_ch1Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq1() ) );
  439. connect( &m_ch2Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq2() ) );
  440. connect( &m_ch3Crs, SIGNAL( dataChanged() ), this, SLOT( updateFreq3() ) );
  441. updateFreq1();
  442. updateFreq2();
  443. updateFreq3();
  444. }
  445. NesInstrument::~NesInstrument()
  446. {
  447. }
  448. void NesInstrument::playNote( NotePlayHandle * n, sampleFrame * workingBuffer )
  449. {
  450. const fpp_t frames = n->framesLeftForCurrentPeriod();
  451. const f_cnt_t offset = n->noteOffset();
  452. if ( n->totalFramesPlayed() == 0 || n->m_pluginData == NULL )
  453. {
  454. NesObject * nes = new NesObject( this, Engine::mixer()->processingSampleRate(), n );
  455. n->m_pluginData = nes;
  456. }
  457. NesObject * nes = static_cast<NesObject *>( n->m_pluginData );
  458. nes->renderOutput( workingBuffer + offset, frames );
  459. applyRelease( workingBuffer, n );
  460. instrumentTrack()->processAudioBuffer( workingBuffer, frames + offset, n );
  461. }
  462. void NesInstrument::deleteNotePluginData( NotePlayHandle * n )
  463. {
  464. delete static_cast<NesObject *>( n->m_pluginData );
  465. }
  466. void NesInstrument::saveSettings( QDomDocument & doc, QDomElement & element )
  467. {
  468. m_ch1Enabled.saveSettings( doc, element, "on1" );
  469. m_ch1Crs.saveSettings( doc, element, "crs1" );
  470. m_ch1Volume.saveSettings( doc, element, "vol1" );
  471. m_ch1EnvEnabled.saveSettings( doc, element, "envon1" );
  472. m_ch1EnvLooped.saveSettings( doc, element, "envloop1" );
  473. m_ch1EnvLen.saveSettings( doc, element, "envlen1" );
  474. m_ch1DutyCycle.saveSettings( doc, element, "dc1" );
  475. m_ch1SweepEnabled.saveSettings( doc, element, "sweep1" );
  476. m_ch1SweepAmt.saveSettings( doc, element, "swamt1" );
  477. m_ch1SweepRate.saveSettings( doc, element, "swrate1" );
  478. // channel 2
  479. m_ch2Enabled.saveSettings( doc, element, "on2" );
  480. m_ch2Crs.saveSettings( doc, element, "crs2" );
  481. m_ch2Volume.saveSettings( doc, element, "vol2" );
  482. m_ch2EnvEnabled.saveSettings( doc, element, "envon2" );
  483. m_ch2EnvLooped.saveSettings( doc, element, "envloop2" );
  484. m_ch2EnvLen.saveSettings( doc, element, "envlen2" );
  485. m_ch2DutyCycle.saveSettings( doc, element, "dc2" );
  486. m_ch2SweepEnabled.saveSettings( doc, element, "sweep2" );
  487. m_ch2SweepAmt.saveSettings( doc, element, "swamt2" );
  488. m_ch2SweepRate.saveSettings( doc, element, "swrate2" );
  489. //channel 3
  490. m_ch3Enabled.saveSettings( doc, element, "on3" );
  491. m_ch3Crs.saveSettings( doc, element, "crs3" );
  492. m_ch3Volume.saveSettings( doc, element, "vol3" );
  493. //channel 4
  494. m_ch4Enabled.saveSettings( doc, element, "on4" );
  495. m_ch4Volume.saveSettings( doc, element, "vol4" );
  496. m_ch4EnvEnabled.saveSettings( doc, element, "envon4" );
  497. m_ch4EnvLooped.saveSettings( doc, element, "envloop4" );
  498. m_ch4EnvLen.saveSettings( doc, element, "envlen4" );
  499. m_ch4NoiseMode.saveSettings( doc, element, "nmode4" );
  500. m_ch4NoiseFreqMode.saveSettings( doc, element, "nfrqmode4" );
  501. m_ch4NoiseFreq.saveSettings( doc, element, "nfreq4" );
  502. m_ch4NoiseQuantize.saveSettings( doc, element, "nq4" );
  503. m_ch4Sweep.saveSettings( doc, element, "nswp4" );
  504. //master
  505. m_masterVol.saveSettings( doc, element, "vol" );
  506. m_vibrato.saveSettings( doc, element, "vibr" );
  507. }
  508. void NesInstrument::loadSettings( const QDomElement & element )
  509. {
  510. m_ch1Enabled.loadSettings( element, "on1" );
  511. m_ch1Crs.loadSettings( element, "crs1" );
  512. m_ch1Volume.loadSettings( element, "vol1" );
  513. m_ch1EnvEnabled.loadSettings( element, "envon1" );
  514. m_ch1EnvLooped.loadSettings( element, "envloop1" );
  515. m_ch1EnvLen.loadSettings( element, "envlen1" );
  516. m_ch1DutyCycle.loadSettings( element, "dc1" );
  517. m_ch1SweepEnabled.loadSettings( element, "sweep1" );
  518. m_ch1SweepAmt.loadSettings( element, "swamt1" );
  519. m_ch1SweepRate.loadSettings( element, "swrate1" );
  520. // channel 2
  521. m_ch2Enabled.loadSettings( element, "on2" );
  522. m_ch2Crs.loadSettings( element, "crs2" );
  523. m_ch2Volume.loadSettings( element, "vol2" );
  524. m_ch2EnvEnabled.loadSettings( element, "envon2" );
  525. m_ch2EnvLooped.loadSettings( element, "envloop2" );
  526. m_ch2EnvLen.loadSettings( element, "envlen2" );
  527. m_ch2DutyCycle.loadSettings( element, "dc2" );
  528. m_ch2SweepEnabled.loadSettings( element, "sweep2" );
  529. m_ch2SweepAmt.loadSettings( element, "swamt2" );
  530. m_ch2SweepRate.loadSettings( element, "swrate2" );
  531. //channel 3
  532. m_ch3Enabled.loadSettings( element, "on3" );
  533. m_ch3Crs.loadSettings( element, "crs3" );
  534. m_ch3Volume.loadSettings( element, "vol3" );
  535. //channel 4
  536. m_ch4Enabled.loadSettings( element, "on4" );
  537. m_ch4Volume.loadSettings( element, "vol4" );
  538. m_ch4EnvEnabled.loadSettings( element, "envon4" );
  539. m_ch4EnvLooped.loadSettings( element, "envloop4" );
  540. m_ch4EnvLen.loadSettings( element, "envlen4" );
  541. m_ch4NoiseMode.loadSettings( element, "nmode4" );
  542. m_ch4NoiseFreqMode.loadSettings( element, "nfrqmode4" );
  543. m_ch4NoiseFreq.loadSettings( element, "nfreq4" );
  544. m_ch4NoiseQuantize.loadSettings( element, "nq4" );
  545. m_ch4Sweep.loadSettings( element, "nswp4" );
  546. //master
  547. m_masterVol.loadSettings( element, "vol" );
  548. m_vibrato.loadSettings( element, "vibr" );
  549. }
  550. QString NesInstrument::nodeName() const
  551. {
  552. return( nes_plugin_descriptor.name );
  553. }
  554. PluginView * NesInstrument::instantiateView( QWidget * parent )
  555. {
  556. return( new NesInstrumentView( this, parent ) );
  557. }
  558. void NesInstrument::updateFreq1()
  559. {
  560. m_freq1 = powf( 2, m_ch1Crs.value() / 12.0f );
  561. }
  562. void NesInstrument::updateFreq2()
  563. {
  564. m_freq2 = powf( 2, m_ch2Crs.value() / 12.0f );
  565. }
  566. void NesInstrument::updateFreq3()
  567. {
  568. m_freq3 = powf( 2, m_ch3Crs.value() / 12.0f );
  569. }
  570. QPixmap * NesInstrumentView::s_artwork = NULL;
  571. NesInstrumentView::NesInstrumentView( Instrument * instrument, QWidget * parent ) :
  572. InstrumentViewFixedSize( instrument, parent )
  573. {
  574. setAutoFillBackground( true );
  575. QPalette pal;
  576. if( s_artwork == NULL )
  577. {
  578. s_artwork = new QPixmap( PLUGIN_NAME::getIconPixmap( "artwork" ) );
  579. }
  580. pal.setBrush( backgroundRole(), *s_artwork );
  581. setPalette( pal );
  582. const int KNOB_Y1 = 24;
  583. const int KNOB_Y2 = 81;
  584. const int KNOB_Y3 = 138;
  585. const int KNOB_Y4 = 195;
  586. const int KNOB_X1 = 12;
  587. const int KNOB_X2 = 46;
  588. const int KNOB_X3 = 84;
  589. const int KNOB_X4 = 117;
  590. const int KNOB_X5 = 151;
  591. const int KNOB_X6 = 172;
  592. const int KNOB_X7 = 206;
  593. // channel 1
  594. makeknob( m_ch1VolumeKnob, KNOB_X1, KNOB_Y1, tr( "Volume" ), "", "" )
  595. makeknob( m_ch1CrsKnob, KNOB_X2, KNOB_Y1, tr( "Coarse detune" ), "", "" )
  596. makeknob( m_ch1EnvLenKnob, KNOB_X3, KNOB_Y1, tr( "Envelope length" ), "", "" )
  597. makenesled( m_ch1EnabledBtn, KNOB_X1, KNOB_Y1 - 12, tr( "Enable channel 1" ) )
  598. makenesled( m_ch1EnvEnabledBtn, KNOB_X3, KNOB_Y1 - 12, tr( "Enable envelope 1" ) )
  599. makenesled( m_ch1EnvLoopedBtn, 129, KNOB_Y1 - 12, tr( "Enable envelope 1 loop" ) )
  600. makenesled( m_ch1SweepEnabledBtn, KNOB_X6, KNOB_Y1 - 12, tr( "Enable sweep 1" ) )
  601. makeknob( m_ch1SweepAmtKnob, KNOB_X6, KNOB_Y1, tr( "Sweep amount" ), "", "" )
  602. makeknob( m_ch1SweepRateKnob, KNOB_X7, KNOB_Y1, tr( "Sweep rate" ), "", "" )
  603. int dcx = 117;
  604. makedcled( ch1_dc1, dcx, 42, tr( "12.5% Duty cycle" ), "nesdc1_on" )
  605. dcx += 13;
  606. makedcled( ch1_dc2, dcx, 42, tr( "25% Duty cycle" ), "nesdc2_on" )
  607. dcx += 13;
  608. makedcled( ch1_dc3, dcx, 42, tr( "50% Duty cycle" ), "nesdc3_on" )
  609. dcx += 13;
  610. makedcled( ch1_dc4, dcx, 42, tr( "75% Duty cycle" ), "nesdc4_on" )
  611. m_ch1DutyCycleGrp = new automatableButtonGroup( this );
  612. m_ch1DutyCycleGrp -> addButton( ch1_dc1 );
  613. m_ch1DutyCycleGrp -> addButton( ch1_dc2 );
  614. m_ch1DutyCycleGrp -> addButton( ch1_dc3 );
  615. m_ch1DutyCycleGrp -> addButton( ch1_dc4 );
  616. // channel 2
  617. makeknob( m_ch2VolumeKnob, KNOB_X1, KNOB_Y2, tr( "Volume" ), "", "" )
  618. makeknob( m_ch2CrsKnob, KNOB_X2, KNOB_Y2, tr( "Coarse detune" ), "", "" )
  619. makeknob( m_ch2EnvLenKnob, KNOB_X3, KNOB_Y2, tr( "Envelope length" ), "", "" )
  620. makenesled( m_ch2EnabledBtn, KNOB_X1, KNOB_Y2 - 12, tr( "Enable channel 2" ) )
  621. makenesled( m_ch2EnvEnabledBtn, KNOB_X3, KNOB_Y2 - 12, tr( "Enable envelope 2" ) )
  622. makenesled( m_ch2EnvLoopedBtn, 129, KNOB_Y2 - 12, tr( "Enable envelope 2 loop" ) )
  623. makenesled( m_ch2SweepEnabledBtn, KNOB_X6, KNOB_Y2 - 12, tr( "Enable sweep 2" ) )
  624. makeknob( m_ch2SweepAmtKnob, KNOB_X6, KNOB_Y2, tr( "Sweep amount" ), "", "" )
  625. makeknob( m_ch2SweepRateKnob, KNOB_X7, KNOB_Y2, tr( "Sweep rate" ), "", "" )
  626. dcx = 117;
  627. makedcled( ch2_dc1, dcx, 99, tr( "12.5% Duty cycle" ), "nesdc1_on" )
  628. dcx += 13;
  629. makedcled( ch2_dc2, dcx, 99, tr( "25% Duty cycle" ), "nesdc2_on" )
  630. dcx += 13;
  631. makedcled( ch2_dc3, dcx, 99, tr( "50% Duty cycle" ), "nesdc3_on" )
  632. dcx += 13;
  633. makedcled( ch2_dc4, dcx, 99, tr( "75% Duty cycle" ), "nesdc4_on" )
  634. m_ch2DutyCycleGrp = new automatableButtonGroup( this );
  635. m_ch2DutyCycleGrp -> addButton( ch2_dc1 );
  636. m_ch2DutyCycleGrp -> addButton( ch2_dc2 );
  637. m_ch2DutyCycleGrp -> addButton( ch2_dc3 );
  638. m_ch2DutyCycleGrp -> addButton( ch2_dc4 );
  639. //channel 3
  640. makenesled( m_ch3EnabledBtn, KNOB_X1, KNOB_Y3 - 12, tr( "Enable channel 3" ) )
  641. makeknob( m_ch3VolumeKnob, KNOB_X1, KNOB_Y3, tr( "Volume" ), "", "" )
  642. makeknob( m_ch3CrsKnob, KNOB_X2, KNOB_Y3, tr( "Coarse detune" ), "", "" )
  643. //channel 4
  644. makeknob( m_ch4VolumeKnob, KNOB_X1, KNOB_Y4, tr( "Volume" ), "", "" )
  645. makeknob( m_ch4NoiseFreqKnob, KNOB_X2, KNOB_Y4, tr( "Noise Frequency" ), "", "" )
  646. makeknob( m_ch4EnvLenKnob, KNOB_X3, KNOB_Y4, tr( "Envelope length" ), "", "" )
  647. makeknob( m_ch4SweepKnob, KNOB_X4, KNOB_Y4, tr( "Frequency sweep" ), "", "" )
  648. makenesled( m_ch4EnabledBtn, KNOB_X1, KNOB_Y4 - 12, tr( "Enable channel 4" ) )
  649. makenesled( m_ch4EnvEnabledBtn, KNOB_X3, KNOB_Y4 - 12, tr( "Enable envelope 4" ) )
  650. makenesled( m_ch4EnvLoopedBtn, 129, KNOB_Y4 - 12, tr( "Enable envelope 4 loop" ) )
  651. makenesled( m_ch4NoiseQuantizeBtn, 162, KNOB_Y4 - 12, tr( "Quantize noise frequency when using note frequency" ) )
  652. makenesled( m_ch4NoiseFreqModeBtn, 148, 203, tr( "Use note frequency for noise" ) )
  653. makenesled( m_ch4NoiseModeBtn, 148, 224, tr( "Noise mode" ) )
  654. //master
  655. makeknob( m_masterVolKnob, KNOB_X4, KNOB_Y3, tr( "Master volume" ), "", "" )
  656. makeknob( m_vibratoKnob, KNOB_X5, KNOB_Y3, tr( "Vibrato" ), "", "" )
  657. }
  658. NesInstrumentView::~NesInstrumentView()
  659. {
  660. }
  661. void NesInstrumentView::modelChanged()
  662. {
  663. NesInstrument * nes = castModel<NesInstrument>();
  664. m_ch1EnabledBtn->setModel( &nes->m_ch1Enabled );
  665. m_ch1CrsKnob->setModel( &nes->m_ch1Crs );
  666. m_ch1VolumeKnob->setModel( &nes->m_ch1Volume );
  667. m_ch1EnvEnabledBtn->setModel( &nes->m_ch1EnvEnabled );
  668. m_ch1EnvLoopedBtn->setModel( &nes->m_ch1EnvLooped );
  669. m_ch1EnvLenKnob->setModel( &nes->m_ch1EnvLen );
  670. m_ch1DutyCycleGrp->setModel( &nes->m_ch1DutyCycle );
  671. m_ch1SweepEnabledBtn->setModel( &nes->m_ch1SweepEnabled );
  672. m_ch1SweepAmtKnob->setModel( &nes->m_ch1SweepAmt );
  673. m_ch1SweepRateKnob->setModel( &nes->m_ch1SweepRate );
  674. // channel 2
  675. m_ch2EnabledBtn->setModel( &nes->m_ch2Enabled );
  676. m_ch2CrsKnob->setModel( &nes->m_ch2Crs );
  677. m_ch2VolumeKnob->setModel( &nes->m_ch2Volume );
  678. m_ch2EnvEnabledBtn->setModel( &nes->m_ch2EnvEnabled );
  679. m_ch2EnvLoopedBtn->setModel( &nes->m_ch2EnvLooped );
  680. m_ch2EnvLenKnob->setModel( &nes->m_ch2EnvLen );
  681. m_ch2DutyCycleGrp->setModel( &nes->m_ch2DutyCycle );
  682. m_ch2SweepEnabledBtn->setModel( &nes->m_ch2SweepEnabled );
  683. m_ch2SweepAmtKnob->setModel( &nes->m_ch2SweepAmt );
  684. m_ch2SweepRateKnob->setModel( &nes->m_ch2SweepRate );
  685. //channel 3
  686. m_ch3EnabledBtn->setModel( &nes->m_ch3Enabled );
  687. m_ch3CrsKnob->setModel( &nes->m_ch3Crs );
  688. m_ch3VolumeKnob->setModel( &nes->m_ch3Volume );
  689. //channel 4
  690. m_ch4EnabledBtn->setModel( &nes->m_ch4Enabled );
  691. m_ch4VolumeKnob->setModel( &nes->m_ch4Volume );
  692. m_ch4EnvEnabledBtn->setModel( &nes->m_ch4EnvEnabled );
  693. m_ch4EnvLoopedBtn->setModel( &nes->m_ch4EnvLooped );
  694. m_ch4EnvLenKnob->setModel( &nes->m_ch4EnvLen );
  695. m_ch4NoiseModeBtn->setModel( &nes->m_ch4NoiseMode );
  696. m_ch4NoiseFreqModeBtn->setModel( &nes->m_ch4NoiseFreqMode );
  697. m_ch4NoiseFreqKnob->setModel( &nes->m_ch4NoiseFreq );
  698. m_ch4SweepKnob->setModel( &nes->m_ch4Sweep );
  699. m_ch4NoiseQuantizeBtn->setModel( &nes->m_ch4NoiseQuantize );
  700. //master
  701. m_masterVolKnob->setModel( &nes->m_masterVol );
  702. m_vibratoKnob->setModel( &nes->m_vibrato );
  703. }
  704. extern "C"
  705. {
  706. // necessary for getting instance out of shared lib
  707. PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * _data )
  708. {
  709. return( new NesInstrument( static_cast<InstrumentTrack *>( m ) ) );
  710. }
  711. }