Nes.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /* Nes.h - 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. #ifndef NES_H
  25. #define NES_H
  26. #include <cmath>
  27. #include "Instrument.h"
  28. #include "InstrumentView.h"
  29. #include "AutomatableModel.h"
  30. #include "AutomatableButton.h"
  31. #include "TempoSyncKnob.h"
  32. #include "NotePlayHandle.h"
  33. #include "PixmapButton.h"
  34. #include "Memory.h"
  35. #define makeknob( name, x, y, hint, unit, oname ) \
  36. name = new Knob( knobStyled, this ); \
  37. name ->move( x, y ); \
  38. name ->setHintText( hint, unit ); \
  39. name ->setObjectName( oname ); \
  40. name ->setFixedSize( 29, 29 );
  41. #define makenesled( name, x, y, ttip ) \
  42. name = new PixmapButton( this, NULL ); \
  43. name -> setCheckable( true ); \
  44. name -> move( x, y ); \
  45. name -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "nesled_on" ) ); \
  46. name -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "nesled_off" ) ); \
  47. ToolTip::add( name, ttip );
  48. #define makedcled( name, x, y, ttip, active ) \
  49. PixmapButton * name = new PixmapButton( this, NULL ); \
  50. name -> move( x, y ); \
  51. name -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( active ) ); \
  52. name -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "nesdc_off" ) ); \
  53. ToolTip::add( name, ttip );
  54. const float NES_SIMPLE_FILTER = 1.0 / 20.0; // simulate nes analog audio output
  55. const float NFB = 895000.0f;
  56. const float NOISE_FREQS[16] =
  57. { NFB/5, NFB/9, NFB/17, NFB/33, NFB/65, NFB/97, NFB/129, NFB/161, NFB/193, NFB/255, NFB/381, NFB/509, NFB/763, NFB/1017, NFB/2035, NFB/4069 };
  58. const uint16_t LFSR_INIT = 1;
  59. const float DUTY_CYCLE[4] = { 0.125, 0.25, 0.5, 0.75 };
  60. const float DITHER_AMP = 1.0 / 60.0;
  61. const float MIN_FREQ = 10.0;
  62. const int TRIANGLE_WAVETABLE[32] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  63. 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
  64. const float NES_DIST = 0.9f; // simulate the slight nonlinear distortion in nes audio output
  65. const float NES_MIXING_12 = 1.0 / 20.0;
  66. const float NES_MIXING_34 = 1.0 / 12.0;
  67. const float NES_MIXING_ALL = 1.0 / ( NES_MIXING_12 + NES_MIXING_34 ); // constants to simulate the hardwired mixing values for nes channels
  68. const int MIN_WLEN = 4;
  69. class NesInstrument;
  70. class NesObject
  71. {
  72. MM_OPERATORS
  73. public:
  74. NesObject( NesInstrument * nes, const sample_rate_t samplerate, NotePlayHandle * nph );
  75. virtual ~NesObject();
  76. void renderOutput( sampleFrame * buf, fpp_t frames );
  77. void updateVibrato( float * freq );
  78. void updatePitch();
  79. void updateLFSR( bool mode )
  80. {
  81. uint16_t LFSRx;
  82. if( mode )
  83. {
  84. LFSRx = m_LFSR & ( 1 << 8 ); // get bit 13
  85. LFSRx <<= 6; // shit to left so it overlaps with bit 14
  86. }
  87. else
  88. {
  89. LFSRx = m_LFSR & ( 1 << 13 ); // get bit 13
  90. LFSRx <<= 1; // shit to left so it overlaps with bit 14
  91. }
  92. m_LFSR ^= LFSRx; // xor bit 14 with bit 8/13 depending on mode
  93. m_LFSR <<= 1; // shift bit 14 to bit 15
  94. // cycle bit 14 to 0
  95. if( m_LFSR & ( 1 << 15 ) ) // if bit 15 is set
  96. {
  97. m_LFSR++; // set bit 0 - we know it to be 0 because of the left shift so we can just inc here
  98. }
  99. }
  100. inline bool LFSR() // returns true if bit 14 is set
  101. {
  102. if( m_LFSR & ( 1 << 14 ) )
  103. {
  104. return true;
  105. }
  106. return false;
  107. }
  108. inline int wavelength( float freq )
  109. {
  110. return static_cast<int>( m_samplerate / freq );
  111. }
  112. inline float signedPow( float f, float e )
  113. {
  114. return f < 0
  115. ? powf( qAbs( f ), e ) * -1.0f
  116. : powf( f, e );
  117. }
  118. inline int nearestNoiseFreq( float f )
  119. {
  120. int n = 15;
  121. for( int i = 15; i >= 0; i-- )
  122. {
  123. if( f >= NOISE_FREQS[ i ] )
  124. {
  125. n = i;
  126. }
  127. }
  128. return n;
  129. }
  130. private:
  131. NesInstrument * m_parent;
  132. const sample_rate_t m_samplerate;
  133. NotePlayHandle * m_nph;
  134. int m_pitchUpdateCounter;
  135. int m_pitchUpdateFreq;
  136. int m_ch1Counter;
  137. int m_ch2Counter;
  138. int m_ch3Counter;
  139. int m_ch4Counter;
  140. int m_ch1EnvCounter;
  141. int m_ch2EnvCounter;
  142. int m_ch4EnvCounter;
  143. int m_ch1EnvValue;
  144. int m_ch2EnvValue;
  145. int m_ch4EnvValue;
  146. int m_ch1SweepCounter;
  147. int m_ch2SweepCounter;
  148. int m_ch4SweepCounter;
  149. uint16_t m_LFSR;
  150. float m_12Last;
  151. float m_34Last;
  152. float m_lastNoteFreq;
  153. float m_lastNoiseFreq;
  154. int m_maxWlen;
  155. float m_nsf;
  156. // wavelengths
  157. int m_wlen1;
  158. int m_wlen2;
  159. int m_wlen3;
  160. int m_wlen4;
  161. // vibrato
  162. int m_vibratoPhase;
  163. };
  164. class NesInstrument : public Instrument
  165. {
  166. Q_OBJECT
  167. public:
  168. NesInstrument( InstrumentTrack * instrumentTrack );
  169. virtual ~NesInstrument();
  170. virtual void playNote( NotePlayHandle * n,
  171. sampleFrame * workingBuffer );
  172. virtual void deleteNotePluginData( NotePlayHandle * n );
  173. virtual void saveSettings( QDomDocument & doc,
  174. QDomElement & element );
  175. virtual void loadSettings( const QDomElement & element );
  176. virtual QString nodeName() const;
  177. virtual f_cnt_t desiredReleaseFrames() const
  178. {
  179. return( 8 );
  180. }
  181. virtual PluginView * instantiateView( QWidget * parent );
  182. public slots:
  183. void updateFreq1();
  184. void updateFreq2();
  185. void updateFreq3();
  186. protected:
  187. //freq helpers
  188. float m_freq1;
  189. float m_freq2;
  190. float m_freq3;
  191. private:
  192. // channel 1
  193. BoolModel m_ch1Enabled;
  194. FloatModel m_ch1Crs;
  195. FloatModel m_ch1Volume;
  196. BoolModel m_ch1EnvEnabled;
  197. BoolModel m_ch1EnvLooped;
  198. FloatModel m_ch1EnvLen;
  199. IntModel m_ch1DutyCycle;
  200. BoolModel m_ch1SweepEnabled;
  201. FloatModel m_ch1SweepAmt;
  202. FloatModel m_ch1SweepRate;
  203. // channel 2
  204. BoolModel m_ch2Enabled;
  205. FloatModel m_ch2Crs;
  206. FloatModel m_ch2Volume;
  207. BoolModel m_ch2EnvEnabled;
  208. BoolModel m_ch2EnvLooped;
  209. FloatModel m_ch2EnvLen;
  210. IntModel m_ch2DutyCycle;
  211. BoolModel m_ch2SweepEnabled;
  212. FloatModel m_ch2SweepAmt;
  213. FloatModel m_ch2SweepRate;
  214. //channel 3
  215. BoolModel m_ch3Enabled;
  216. FloatModel m_ch3Crs;
  217. FloatModel m_ch3Volume;
  218. //channel 4
  219. BoolModel m_ch4Enabled;
  220. FloatModel m_ch4Volume;
  221. BoolModel m_ch4EnvEnabled;
  222. BoolModel m_ch4EnvLooped;
  223. FloatModel m_ch4EnvLen;
  224. BoolModel m_ch4NoiseMode;
  225. BoolModel m_ch4NoiseFreqMode;
  226. FloatModel m_ch4NoiseFreq;
  227. FloatModel m_ch4Sweep;
  228. BoolModel m_ch4NoiseQuantize;
  229. //master
  230. FloatModel m_masterVol;
  231. FloatModel m_vibrato;
  232. friend class NesObject;
  233. friend class NesInstrumentView;
  234. };
  235. class NesInstrumentView : public InstrumentViewFixedSize
  236. {
  237. Q_OBJECT
  238. public:
  239. NesInstrumentView( Instrument * instrument,
  240. QWidget * parent );
  241. virtual ~NesInstrumentView();
  242. private:
  243. virtual void modelChanged();
  244. // channel 1
  245. PixmapButton * m_ch1EnabledBtn;
  246. Knob * m_ch1CrsKnob;
  247. Knob * m_ch1VolumeKnob;
  248. PixmapButton * m_ch1EnvEnabledBtn;
  249. PixmapButton * m_ch1EnvLoopedBtn;
  250. Knob * m_ch1EnvLenKnob;
  251. automatableButtonGroup * m_ch1DutyCycleGrp;
  252. PixmapButton * m_ch1SweepEnabledBtn;
  253. Knob * m_ch1SweepAmtKnob;
  254. Knob * m_ch1SweepRateKnob;
  255. // channel 2
  256. PixmapButton * m_ch2EnabledBtn;
  257. Knob * m_ch2CrsKnob;
  258. Knob * m_ch2VolumeKnob;
  259. PixmapButton * m_ch2EnvEnabledBtn;
  260. PixmapButton * m_ch2EnvLoopedBtn;
  261. Knob * m_ch2EnvLenKnob;
  262. automatableButtonGroup * m_ch2DutyCycleGrp;
  263. PixmapButton * m_ch2SweepEnabledBtn;
  264. Knob * m_ch2SweepAmtKnob;
  265. Knob * m_ch2SweepRateKnob;
  266. //channel 3
  267. PixmapButton * m_ch3EnabledBtn;
  268. Knob * m_ch3CrsKnob;
  269. Knob * m_ch3VolumeKnob;
  270. //channel 4
  271. PixmapButton * m_ch4EnabledBtn;
  272. Knob * m_ch4VolumeKnob;
  273. PixmapButton * m_ch4EnvEnabledBtn;
  274. PixmapButton * m_ch4EnvLoopedBtn;
  275. Knob * m_ch4EnvLenKnob;
  276. PixmapButton * m_ch4NoiseModeBtn;
  277. PixmapButton * m_ch4NoiseFreqModeBtn;
  278. Knob * m_ch4NoiseFreqKnob;
  279. Knob * m_ch4SweepKnob;
  280. PixmapButton * m_ch4NoiseQuantizeBtn;
  281. //master
  282. Knob * m_masterVolKnob;
  283. Knob * m_vibratoKnob;
  284. static QPixmap * s_artwork;
  285. };
  286. #endif