papu_instrument.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. /*
  2. * papu_instrument.cpp - GameBoy papu based instrument
  3. *
  4. * Copyright (c) 2008 Attila Herman <attila589/at/gmail.com>
  5. * Csaba Hruska <csaba.hruska/at/gmail.com>
  6. *
  7. * This file is part of LMMS - https://lmms.io
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public
  20. * License along with this program (see COPYING); if not, write to the
  21. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  22. * Boston, MA 02110-1301 USA.
  23. *
  24. */
  25. #include <cmath>
  26. #include <QPainter>
  27. #include <QDomElement>
  28. #include "Basic_Gb_Apu.h"
  29. #include "papu_instrument.h"
  30. #include "base64.h"
  31. #include "InstrumentTrack.h"
  32. #include "Knob.h"
  33. #include "Mixer.h"
  34. #include "NotePlayHandle.h"
  35. #include "PixmapButton.h"
  36. #include "ToolTip.h"
  37. #include "Engine.h"
  38. #include "Graph.h"
  39. #include "embed.cpp"
  40. extern "C"
  41. {
  42. Plugin::Descriptor PLUGIN_EXPORT papu_plugin_descriptor =
  43. {
  44. STRINGIFY( PLUGIN_NAME ),
  45. "FreeBoy",
  46. QT_TRANSLATE_NOOP( "pluginBrowser", "Emulation of GameBoy (TM) APU" ),
  47. "Attila Herman <attila589/at/gmail.com>"
  48. "Csaba Hruska <csaba.hruska/at/gmail.com>",
  49. 0x0100,
  50. Plugin::Instrument,
  51. new PluginPixmapLoader( "logo" ),
  52. NULL
  53. } ;
  54. }
  55. papuInstrument::papuInstrument( InstrumentTrack * _instrument_track ) :
  56. Instrument( _instrument_track, &papu_plugin_descriptor ),
  57. m_ch1SweepTimeModel( 4.0f, 0.0f, 7.0f, 1.0f, this, tr( "Sweep time" ) ),
  58. m_ch1SweepDirModel( false, this, tr( "Sweep direction" ) ),
  59. m_ch1SweepRtShiftModel( 4.0f, 0.0f, 7.0f, 1.0f, this,
  60. tr( "Sweep RtShift amount" ) ),
  61. m_ch1WavePatternDutyModel( 2.0f, 0.0f, 3.0f, 1.0f, this,
  62. tr( "Wave Pattern Duty" ) ),
  63. m_ch1VolumeModel( 15.0f, 0.0f, 15.0f, 1.0f, this,
  64. tr( "Channel 1 volume" ) ),
  65. m_ch1VolSweepDirModel( false, this,
  66. tr( "Volume sweep direction" ) ),
  67. m_ch1SweepStepLengthModel( 0.0f, 0.0f, 7.0f, 1.0f, this,
  68. tr( "Length of each step in sweep" ) ),
  69. m_ch2WavePatternDutyModel( 2.0f, 0.0f, 3.0f, 1.0f, this,
  70. tr( "Wave Pattern Duty" ) ),
  71. m_ch2VolumeModel( 15.0f, 0.0f, 15.0f, 1.0f, this,
  72. tr( "Channel 2 volume" ) ),
  73. m_ch2VolSweepDirModel( false, this,
  74. tr( "Volume sweep direction" ) ),
  75. m_ch2SweepStepLengthModel( 0.0f, 0.0f, 7.0f, 1.0f, this,
  76. tr( "Length of each step in sweep" ) ),
  77. //m_ch3OnModel( true, this, tr( "Channel 3 Master on/off" ) ),
  78. m_ch3VolumeModel( 3.0f, 0.0f, 3.0f, 1.0f, this,
  79. tr( "Channel 3 volume" ) ),
  80. m_ch4VolumeModel( 15.0f, 0.0f, 15.0f, 1.0f, this,
  81. tr( "Channel 4 volume" ) ),
  82. m_ch4VolSweepDirModel( false, this,
  83. tr( "Volume sweep direction" ) ),
  84. m_ch4SweepStepLengthModel( 0.0f, 0.0f, 7.0f, 1.0f, this,
  85. tr( "Length of each step in sweep" ) ),
  86. m_ch4ShiftRegWidthModel( false, this,
  87. tr( "Shift Register width" ) ),
  88. m_so1VolumeModel( 7.0f, 0.0f, 7.0f, 1.0f, this, tr( "Right Output level") ),
  89. m_so2VolumeModel( 7.0f, 0.0f, 7.0f, 1.0f, this, tr( "Left Output level" ) ),
  90. m_ch1So1Model( true, this, tr( "Channel 1 to SO2 (Left)" ) ),
  91. m_ch2So1Model( true, this, tr( "Channel 2 to SO2 (Left)" ) ),
  92. m_ch3So1Model( true, this, tr( "Channel 3 to SO2 (Left)" ) ),
  93. m_ch4So1Model( false, this, tr( "Channel 4 to SO2 (Left)" ) ),
  94. m_ch1So2Model( true, this, tr( "Channel 1 to SO1 (Right)" ) ),
  95. m_ch2So2Model( true, this, tr( "Channel 2 to SO1 (Right)" ) ),
  96. m_ch3So2Model( true, this, tr( "Channel 3 to SO1 (Right)" ) ),
  97. m_ch4So2Model( false, this, tr( "Channel 4 to SO1 (Right)" ) ),
  98. m_trebleModel( -20.0f, -100.0f, 200.0f, 1.0f, this, tr( "Treble" ) ),
  99. m_bassModel( 461.0f, -1.0f, 600.0f, 1.0f, this, tr( "Bass" ) ),
  100. m_graphModel( 0, 15, 32, this, false, 1 )
  101. {
  102. }
  103. papuInstrument::~papuInstrument()
  104. {
  105. }
  106. void papuInstrument::saveSettings( QDomDocument & _doc,
  107. QDomElement & _this )
  108. {
  109. m_ch1SweepTimeModel.saveSettings( _doc, _this, "st" );
  110. m_ch1SweepDirModel.saveSettings( _doc, _this, "sd" );
  111. m_ch1SweepRtShiftModel.saveSettings( _doc, _this, "srs" );
  112. m_ch1WavePatternDutyModel.saveSettings( _doc, _this, "ch1wpd" );
  113. m_ch1VolumeModel.saveSettings( _doc, _this, "ch1vol" );
  114. m_ch1VolSweepDirModel.saveSettings( _doc, _this, "ch1vsd" );
  115. m_ch1SweepStepLengthModel.saveSettings( _doc, _this, "ch1ssl" );
  116. m_ch2WavePatternDutyModel.saveSettings( _doc, _this, "ch2wpd" );
  117. m_ch2VolumeModel.saveSettings( _doc, _this, "ch2vol" );
  118. m_ch2VolSweepDirModel.saveSettings( _doc, _this, "ch2vsd" );
  119. m_ch2SweepStepLengthModel.saveSettings( _doc, _this, "ch2ssl" );
  120. //m_ch3OnModel.saveSettings( _doc, _this, "ch3on" );
  121. m_ch3VolumeModel.saveSettings( _doc, _this, "ch3vol" );
  122. m_ch4VolumeModel.saveSettings( _doc, _this, "ch4vol" );
  123. m_ch4VolSweepDirModel.saveSettings( _doc, _this, "ch4vsd" );
  124. m_ch4SweepStepLengthModel.saveSettings( _doc, _this, "ch4ssl" );
  125. m_ch4ShiftRegWidthModel.saveSettings( _doc, _this, "srw" );
  126. m_so1VolumeModel.saveSettings( _doc, _this, "so1vol" );
  127. m_so2VolumeModel.saveSettings( _doc, _this, "so2vol" );
  128. m_ch1So1Model.saveSettings( _doc, _this, "ch1so2" );
  129. m_ch2So1Model.saveSettings( _doc, _this, "ch2so2" );
  130. m_ch3So1Model.saveSettings( _doc, _this, "ch3so2" );
  131. m_ch4So1Model.saveSettings( _doc, _this, "ch4so2" );
  132. m_ch1So2Model.saveSettings( _doc, _this, "ch1so1" );
  133. m_ch2So2Model.saveSettings( _doc, _this, "ch2so1" );
  134. m_ch3So2Model.saveSettings( _doc, _this, "ch3so1" );
  135. m_ch4So2Model.saveSettings( _doc, _this, "ch4so1" );
  136. m_trebleModel.saveSettings( _doc, _this, "Treble" );
  137. m_bassModel.saveSettings( _doc, _this, "Bass" );
  138. QString sampleString;
  139. base64::encode( (const char *)m_graphModel.samples(),
  140. m_graphModel.length() * sizeof(float), sampleString );
  141. _this.setAttribute( "sampleShape", sampleString );
  142. }
  143. void papuInstrument::loadSettings( const QDomElement & _this )
  144. {
  145. m_ch1SweepTimeModel.loadSettings( _this, "st" );
  146. m_ch1SweepDirModel.loadSettings( _this, "sd" );
  147. m_ch1SweepRtShiftModel.loadSettings( _this, "srs" );
  148. m_ch1WavePatternDutyModel.loadSettings( _this, "ch1wpd" );
  149. m_ch1VolumeModel.loadSettings( _this, "ch1vol" );
  150. m_ch1VolSweepDirModel.loadSettings( _this, "ch1vsd" );
  151. m_ch1SweepStepLengthModel.loadSettings( _this, "ch1ssl" );
  152. m_ch2WavePatternDutyModel.loadSettings( _this, "ch2wpd" );
  153. m_ch2VolumeModel.loadSettings( _this, "ch2vol" );
  154. m_ch2VolSweepDirModel.loadSettings( _this, "ch2vsd" );
  155. m_ch2SweepStepLengthModel.loadSettings( _this, "ch2ssl" );
  156. //m_ch3OnModel.loadSettings( _this, "ch3on" );
  157. m_ch3VolumeModel.loadSettings( _this, "ch3vol" );
  158. m_ch4VolumeModel.loadSettings( _this, "ch4vol" );
  159. m_ch4VolSweepDirModel.loadSettings( _this, "ch4vsd" );
  160. m_ch4SweepStepLengthModel.loadSettings( _this, "ch4ssl" );
  161. m_ch4ShiftRegWidthModel.loadSettings( _this, "srw" );
  162. m_so1VolumeModel.loadSettings( _this, "so1vol" );
  163. m_so2VolumeModel.loadSettings( _this, "so2vol" );
  164. m_ch1So1Model.loadSettings( _this, "ch1so2" );
  165. m_ch2So1Model.loadSettings( _this, "ch2so2" );
  166. m_ch3So1Model.loadSettings( _this, "ch3so2" );
  167. m_ch4So1Model.loadSettings( _this, "ch4so2" );
  168. m_ch1So2Model.loadSettings( _this, "ch1so1" );
  169. m_ch2So2Model.loadSettings( _this, "ch2so1" );
  170. m_ch3So2Model.loadSettings( _this, "ch3so1" );
  171. m_ch4So2Model.loadSettings( _this, "ch4so1" );
  172. m_trebleModel.loadSettings( _this, "Treble" );
  173. m_bassModel.loadSettings( _this, "Bass" );
  174. int size = 0;
  175. char * dst = 0;
  176. base64::decode( _this.attribute( "sampleShape"), &dst, &size );
  177. m_graphModel.setSamples( (float*) dst );
  178. }
  179. QString papuInstrument::nodeName() const
  180. {
  181. return( papu_plugin_descriptor.name );
  182. }
  183. /*f_cnt_t papuInstrument::desiredReleaseFrames() const
  184. {
  185. const float samplerate = Engine::mixer()->processingSampleRate();
  186. int maxrel = 0;
  187. for( int i = 0 ; i < 3 ; ++i )
  188. {
  189. if( maxrel < m_voice[i]->m_releaseModel.value() )
  190. maxrel = m_voice[i]->m_releaseModel.value();
  191. }
  192. return f_cnt_t( float(relTime[maxrel])*samplerate/1000.0 );
  193. }*/
  194. f_cnt_t papuInstrument::desiredReleaseFrames() const
  195. {
  196. return f_cnt_t( 1000 );
  197. }
  198. void papuInstrument::playNote( NotePlayHandle * _n,
  199. sampleFrame * _working_buffer )
  200. {
  201. const f_cnt_t tfp = _n->totalFramesPlayed();
  202. const int samplerate = Engine::mixer()->processingSampleRate();
  203. const fpp_t frames = _n->framesLeftForCurrentPeriod();
  204. const f_cnt_t offset = _n->noteOffset();
  205. int data = 0;
  206. int freq = _n->frequency();
  207. if ( tfp == 0 )
  208. {
  209. Basic_Gb_Apu *papu = new Basic_Gb_Apu();
  210. papu->set_sample_rate( samplerate );
  211. // Master sound circuitry power control
  212. papu->write_register( 0xff26, 0x80 );
  213. data = m_ch1VolumeModel.value();
  214. data = data<<1;
  215. data += m_ch1VolSweepDirModel.value();
  216. data = data<<3;
  217. data += m_ch1SweepStepLengthModel.value();
  218. papu->write_register( 0xff12, data );
  219. data = m_ch2VolumeModel.value();
  220. data = data<<1;
  221. data += m_ch2VolSweepDirModel.value();
  222. data = data<<3;
  223. data += m_ch2SweepStepLengthModel.value();
  224. papu->write_register( 0xff17, data );
  225. //channel 4 - noise
  226. data = m_ch4VolumeModel.value();
  227. data = data<<1;
  228. data += m_ch4VolSweepDirModel.value();
  229. data = data<<3;
  230. data += m_ch4SweepStepLengthModel.value();
  231. papu->write_register( 0xff21, data );
  232. _n->m_pluginData = papu;
  233. }
  234. Basic_Gb_Apu *papu = static_cast<Basic_Gb_Apu *>( _n->m_pluginData );
  235. papu->treble_eq( m_trebleModel.value() );
  236. papu->bass_freq( m_bassModel.value() );
  237. //channel 1 - square
  238. data = m_ch1SweepTimeModel.value();
  239. data = data<<1;
  240. data += m_ch1SweepDirModel.value();
  241. data = data << 3;
  242. data += m_ch1SweepRtShiftModel.value();
  243. papu->write_register( 0xff10, data );
  244. data = m_ch1WavePatternDutyModel.value();
  245. data = data<<6;
  246. papu->write_register( 0xff11, data );
  247. //channel 2 - square
  248. data = m_ch2WavePatternDutyModel.value();
  249. data = data<<6;
  250. papu->write_register( 0xff16, data );
  251. //channel 3 - wave
  252. //data = m_ch3OnModel.value()?128:0;
  253. data = 128;
  254. papu->write_register( 0xff1a, data );
  255. int ch3voldata[4] = { 0, 3, 2, 1 };
  256. data = ch3voldata[(int)m_ch3VolumeModel.value()];
  257. data = data<<5;
  258. papu->write_register( 0xff1c, data );
  259. //controls
  260. data = m_so1VolumeModel.value();
  261. data = data<<4;
  262. data += m_so2VolumeModel.value();
  263. papu->write_register( 0xff24, data );
  264. data = m_ch4So2Model.value()?128:0;
  265. data += m_ch3So2Model.value()?64:0;
  266. data += m_ch2So2Model.value()?32:0;
  267. data += m_ch1So2Model.value()?16:0;
  268. data += m_ch4So1Model.value()?8:0;
  269. data += m_ch3So1Model.value()?4:0;
  270. data += m_ch2So1Model.value()?2:0;
  271. data += m_ch1So1Model.value()?1:0;
  272. papu->write_register( 0xff25, data );
  273. const float * wpm = m_graphModel.samples();
  274. for( char i=0; i<16; i++ )
  275. {
  276. data = (int)floor(wpm[i*2]) << 4;
  277. data += (int)floor(wpm[i*2+1]);
  278. papu->write_register( 0xff30 + i, data );
  279. }
  280. if( ( freq >= 65 ) && ( freq <=4000 ) )
  281. {
  282. int initflag = (tfp==0)?128:0;
  283. // Hz = 4194304 / ( ( 2048 - ( 11-bit-freq ) ) << 5 )
  284. data = 2048 - ( ( 4194304 / freq )>>5 );
  285. if( tfp==0 )
  286. {
  287. papu->write_register( 0xff13, data & 0xff );
  288. papu->write_register( 0xff14, (data>>8) | initflag );
  289. }
  290. papu->write_register( 0xff18, data & 0xff );
  291. papu->write_register( 0xff19, (data>>8) | initflag );
  292. papu->write_register( 0xff1d, data & 0xff );
  293. papu->write_register( 0xff1e, (data>>8) | initflag );
  294. }
  295. if( tfp == 0 )
  296. {
  297. //PRNG Frequency = (1048576 Hz / (ratio + 1)) / 2 ^ (shiftclockfreq + 1)
  298. char sopt=0;
  299. char ropt=1;
  300. float fopt = 524288.0 / ( ropt * pow( 2.0, sopt + 1.0 ) );
  301. float f;
  302. for ( char s=0; s<16; s++ )
  303. for ( char r=0; r<8; r++ ) {
  304. f = 524288.0 / ( r * pow( 2.0, s + 1.0 ) );
  305. if( fabs( freq-fopt ) > fabs( freq-f ) ) {
  306. fopt = f;
  307. ropt = r;
  308. sopt = s;
  309. }
  310. }
  311. data = sopt;
  312. data = data << 1;
  313. data += m_ch4ShiftRegWidthModel.value();
  314. data = data << 3;
  315. data += ropt;
  316. papu->write_register( 0xff22, data );
  317. //channel 4 init
  318. papu->write_register( 0xff23, 128 );
  319. }
  320. int const buf_size = 2048;
  321. int framesleft = frames;
  322. int datalen = 0;
  323. blip_sample_t buf [buf_size*2];
  324. while( framesleft > 0 )
  325. {
  326. int avail = papu->samples_avail();
  327. if( avail <= 0 )
  328. {
  329. papu->end_frame();
  330. avail = papu->samples_avail();
  331. }
  332. datalen = framesleft>avail?avail:framesleft;
  333. datalen = datalen>buf_size?buf_size:datalen;
  334. long count = papu->read_samples( buf, datalen*2)/2;
  335. for( fpp_t frame = 0; frame < count; ++frame )
  336. {
  337. for( ch_cnt_t ch = 0; ch < DEFAULT_CHANNELS; ++ch )
  338. {
  339. sample_t s = float(buf[frame*2+ch])/32768.0;
  340. _working_buffer[frames-framesleft+frame+offset][ch] = s;
  341. }
  342. }
  343. framesleft -= count;
  344. }
  345. instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n );
  346. }
  347. void papuInstrument::deleteNotePluginData( NotePlayHandle * _n )
  348. {
  349. delete static_cast<Basic_Gb_Apu *>( _n->m_pluginData );
  350. }
  351. PluginView * papuInstrument::instantiateView( QWidget * _parent )
  352. {
  353. return( new papuInstrumentView( this, _parent ) );
  354. }
  355. class papuKnob : public Knob
  356. {
  357. public:
  358. papuKnob( QWidget * _parent ) :
  359. Knob( knobStyled, _parent )
  360. {
  361. setFixedSize( 30, 30 );
  362. setCenterPointX( 15.0 );
  363. setCenterPointY( 15.0 );
  364. setInnerRadius( 8 );
  365. setOuterRadius( 13 );
  366. setTotalAngle( 270.0 );
  367. setLineWidth( 1 );
  368. setOuterColor( QColor( 0xF1, 0xFF, 0x93 ) );
  369. }
  370. };
  371. papuInstrumentView::papuInstrumentView( Instrument * _instrument,
  372. QWidget * _parent ) :
  373. InstrumentView( _instrument, _parent )
  374. {
  375. setAutoFillBackground( true );
  376. QPalette pal;
  377. pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
  378. setPalette( pal );
  379. m_ch1SweepTimeKnob = new papuKnob( this );
  380. m_ch1SweepTimeKnob->setHintText( tr( "Sweep Time:" ), "" );
  381. m_ch1SweepTimeKnob->move( 5 + 4*32, 106 );
  382. ToolTip::add( m_ch1SweepTimeKnob, tr( "Sweep Time" ) );
  383. m_ch1SweepTimeKnob->setWhatsThis( tr( "The amount of increase or"
  384. " decrease in frequency" ) );
  385. m_ch1SweepRtShiftKnob = new papuKnob( this );
  386. m_ch1SweepRtShiftKnob->setHintText( tr( "Sweep RtShift amount:" )
  387. , "" );
  388. m_ch1SweepRtShiftKnob->move( 5 + 3*32, 106 );
  389. ToolTip::add( m_ch1SweepRtShiftKnob, tr( "Sweep RtShift amount" ) );
  390. m_ch1SweepRtShiftKnob->setWhatsThis( tr( "The rate at which increase or"
  391. " decrease in frequency occurs" ) );
  392. m_ch1WavePatternDutyKnob = new papuKnob( this );
  393. m_ch1WavePatternDutyKnob->setHintText( tr( "Wave pattern duty:" )
  394. , "" );
  395. m_ch1WavePatternDutyKnob->move( 5 + 2*32, 106 );
  396. ToolTip::add( m_ch1WavePatternDutyKnob, tr( "Wave Pattern Duty" ) );
  397. m_ch1WavePatternDutyKnob->setWhatsThis( tr( "The duty cycle is the ratio of"
  398. " the duration (time) that a signal is ON"
  399. " versus the total period of the signal." ) );
  400. m_ch1VolumeKnob = new papuKnob( this );
  401. m_ch1VolumeKnob->setHintText( tr( "Square Channel 1 Volume:" )
  402. , "" );
  403. m_ch1VolumeKnob->move( 5, 106 );
  404. ToolTip::add( m_ch1VolumeKnob, tr( "Square Channel 1 Volume:" ) );
  405. m_ch1VolumeKnob->setWhatsThis( tr( "Square Channel 1 Volume" ) );
  406. m_ch1SweepStepLengthKnob = new papuKnob( this );
  407. m_ch1SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" )
  408. , "" );
  409. m_ch1SweepStepLengthKnob->move( 5 + 32, 106 );
  410. ToolTip::add( m_ch1SweepStepLengthKnob, tr( "Length of each step in sweep" ) );
  411. m_ch1SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) );
  412. m_ch2WavePatternDutyKnob = new papuKnob( this );
  413. m_ch2WavePatternDutyKnob->setHintText( tr( "Wave pattern duty:" )
  414. , "" );
  415. m_ch2WavePatternDutyKnob->move( 5 + 2*32, 155 );
  416. ToolTip::add( m_ch2WavePatternDutyKnob, tr( "Wave pattern duty" ) );
  417. m_ch2WavePatternDutyKnob->setWhatsThis( tr( "The duty cycle is the ratio of"
  418. " the duration (time) that a signal is ON"
  419. " versus the total period of the signal." ) );
  420. m_ch2VolumeKnob = new papuKnob( this );
  421. m_ch2VolumeKnob->setHintText( tr( "Square Channel 2 Volume:" )
  422. , "" );
  423. m_ch2VolumeKnob->move( 5, 155 );
  424. ToolTip::add( m_ch2VolumeKnob, tr( "Square Channel 2 Volume" ) );
  425. m_ch2VolumeKnob->setWhatsThis( tr( "Square Channel 2 Volume" ) );
  426. m_ch2SweepStepLengthKnob = new papuKnob( this );
  427. m_ch2SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" )
  428. , "" );
  429. m_ch2SweepStepLengthKnob->move( 5 + 32, 155 );
  430. ToolTip::add( m_ch2SweepStepLengthKnob, tr( "Length of each step in sweep" ) );
  431. m_ch2SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) );
  432. m_ch3VolumeKnob = new papuKnob( this );
  433. m_ch3VolumeKnob->setHintText( tr( "Wave Channel Volume:" ), "" );
  434. m_ch3VolumeKnob->move( 5, 204 );
  435. ToolTip::add( m_ch3VolumeKnob, tr( "Wave Channel Volume" ) );
  436. m_ch3VolumeKnob->setWhatsThis( tr( "Wave Channel Volume" ) );
  437. m_ch4VolumeKnob = new papuKnob( this );
  438. m_ch4VolumeKnob->setHintText( tr( "Noise Channel Volume:" ), "" );
  439. m_ch4VolumeKnob->move( 144, 155 );
  440. ToolTip::add( m_ch4VolumeKnob, tr( "Noise Channel Volume" ) );
  441. m_ch4VolumeKnob->setWhatsThis( tr( "Noise Channel Volume" ) );
  442. m_ch4SweepStepLengthKnob = new papuKnob( this );
  443. m_ch4SweepStepLengthKnob->setHintText( tr( "Length of each step in sweep:" )
  444. , "" );
  445. m_ch4SweepStepLengthKnob->move( 144 + 32, 155 );
  446. ToolTip::add( m_ch4SweepStepLengthKnob, tr( "Length of each step in sweep" ) );
  447. m_ch4SweepStepLengthKnob->setWhatsThis( tr( "The delay between step change" ) );
  448. m_so1VolumeKnob = new papuKnob( this );
  449. m_so1VolumeKnob->setHintText( tr( "SO1 Volume (Right):" ), "" );
  450. m_so1VolumeKnob->move( 5, 58 );
  451. ToolTip::add( m_so1VolumeKnob, tr( "SO1 Volume (Right)" ) );
  452. m_so2VolumeKnob = new papuKnob( this );
  453. m_so2VolumeKnob->setHintText( tr( "SO2 Volume (Left):" ), "" );
  454. m_so2VolumeKnob->move( 5 + 32, 58 );
  455. ToolTip::add( m_so2VolumeKnob, tr( "SO2 Volume (Left)" ) );
  456. m_trebleKnob = new papuKnob( this );
  457. m_trebleKnob->setHintText( tr( "Treble:" ), "" );
  458. m_trebleKnob->move( 5 + 2*32, 58 );
  459. ToolTip::add( m_trebleKnob, tr( "Treble" ) );
  460. m_bassKnob = new papuKnob( this );
  461. m_bassKnob->setHintText( tr( "Bass:" ), "" );
  462. m_bassKnob->move( 5 + 3*32, 58 );
  463. ToolTip::add( m_bassKnob, tr( "Bass" ) );
  464. m_ch1SweepDirButton = new PixmapButton( this, NULL );
  465. m_ch1SweepDirButton->setCheckable( true );
  466. m_ch1SweepDirButton->move( 167, 108 );
  467. m_ch1SweepDirButton->setActiveGraphic(
  468. PLUGIN_NAME::getIconPixmap( "btn_down" ) );
  469. m_ch1SweepDirButton->setInactiveGraphic(
  470. PLUGIN_NAME::getIconPixmap( "btn_up" ) );
  471. ToolTip::add( m_ch1SweepDirButton, tr( "Sweep Direction" ) );
  472. m_ch1VolSweepDirButton = new PixmapButton( this, NULL );
  473. m_ch1VolSweepDirButton->setCheckable( true );
  474. m_ch1VolSweepDirButton->move( 207, 108 );
  475. m_ch1VolSweepDirButton->setActiveGraphic(
  476. PLUGIN_NAME::getIconPixmap( "btn_up" ) );
  477. m_ch1VolSweepDirButton->setInactiveGraphic(
  478. PLUGIN_NAME::getIconPixmap( "btn_down" ) );
  479. ToolTip::add( m_ch1VolSweepDirButton, tr( "Volume Sweep Direction" ) );
  480. m_ch2VolSweepDirButton = new PixmapButton( this,
  481. tr( "Volume Sweep Direction" ) );
  482. m_ch2VolSweepDirButton->setCheckable( true );
  483. m_ch2VolSweepDirButton->move( 102, 156 );
  484. m_ch2VolSweepDirButton->setActiveGraphic(
  485. PLUGIN_NAME::getIconPixmap( "btn_up" ) );
  486. m_ch2VolSweepDirButton->setInactiveGraphic(
  487. PLUGIN_NAME::getIconPixmap( "btn_down" ) );
  488. ToolTip::add( m_ch2VolSweepDirButton, tr( "Volume Sweep Direction" ) );
  489. //m_ch3OnButton = new PixmapButton( this, NULL );
  490. //m_ch3OnButton->move( 176, 53 );
  491. m_ch4VolSweepDirButton = new PixmapButton( this,
  492. tr( "Volume Sweep Direction" ) );
  493. m_ch4VolSweepDirButton->setCheckable( true );
  494. m_ch4VolSweepDirButton->move( 207, 157 );
  495. m_ch4VolSweepDirButton->setActiveGraphic(
  496. PLUGIN_NAME::getIconPixmap( "btn_up" ) );
  497. m_ch4VolSweepDirButton->setInactiveGraphic(
  498. PLUGIN_NAME::getIconPixmap( "btn_down" ) );
  499. ToolTip::add( m_ch4VolSweepDirButton, tr( "Volume Sweep Direction" ) );
  500. m_ch4ShiftRegWidthButton = new PixmapButton( this, NULL );
  501. m_ch4ShiftRegWidthButton->setCheckable( true );
  502. m_ch4ShiftRegWidthButton->move( 207, 171 );
  503. m_ch4ShiftRegWidthButton->setActiveGraphic(
  504. PLUGIN_NAME::getIconPixmap( "btn_7" ) );
  505. m_ch4ShiftRegWidthButton->setInactiveGraphic(
  506. PLUGIN_NAME::getIconPixmap( "btn_15" ) );
  507. ToolTip::add( m_ch4ShiftRegWidthButton, tr( "Shift Register Width" ) );
  508. m_ch1So1Button = new PixmapButton( this, NULL );
  509. m_ch1So1Button->setCheckable( true );
  510. m_ch1So1Button->move( 208, 51 );
  511. m_ch1So1Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  512. m_ch1So1Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  513. ToolTip::add( m_ch1So1Button, tr( "Channel1 to SO1 (Right)" ) );
  514. m_ch2So1Button = new PixmapButton( this, NULL );
  515. m_ch2So1Button->setCheckable( true );
  516. m_ch2So1Button->move( 208, 51 + 12 );
  517. m_ch2So1Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  518. m_ch2So1Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  519. ToolTip::add( m_ch2So1Button, tr( "Channel2 to SO1 (Right)" ) );
  520. m_ch3So1Button = new PixmapButton( this, NULL );
  521. m_ch3So1Button->setCheckable( true );
  522. m_ch3So1Button->move( 208, 51 + 2*12 );
  523. m_ch3So1Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  524. m_ch3So1Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  525. ToolTip::add( m_ch3So1Button, tr( "Channel3 to SO1 (Right)" ) );
  526. m_ch4So1Button = new PixmapButton( this, NULL );
  527. m_ch4So1Button->setCheckable( true );
  528. m_ch4So1Button->setChecked( false );
  529. m_ch4So1Button->move( 208, 51 + 3*12 );
  530. m_ch4So1Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  531. m_ch4So1Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  532. ToolTip::add( m_ch4So1Button, tr( "Channel4 to SO1 (Right)" ) );
  533. m_ch1So2Button = new PixmapButton( this, NULL );
  534. m_ch1So2Button->setCheckable( true );
  535. m_ch1So2Button->move( 148, 51 );
  536. m_ch1So2Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  537. m_ch1So2Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  538. ToolTip::add( m_ch1So2Button, tr( "Channel1 to SO2 (Left)" ) );
  539. m_ch2So2Button = new PixmapButton( this, NULL );
  540. m_ch2So2Button->setCheckable( true );
  541. m_ch2So2Button->move( 148, 51 + 12 );
  542. m_ch2So2Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  543. m_ch2So2Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  544. ToolTip::add( m_ch2So2Button, tr( "Channel2 to SO2 (Left)" ) );
  545. m_ch3So2Button = new PixmapButton( this, NULL );
  546. m_ch3So2Button->setCheckable( true );
  547. m_ch3So2Button->move( 148, 51 + 2*12 );
  548. m_ch3So2Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  549. m_ch3So2Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  550. ToolTip::add( m_ch3So2Button, tr( "Channel3 to SO2 (Left)" ) );
  551. m_ch4So2Button = new PixmapButton( this, NULL );
  552. m_ch4So2Button->setCheckable( true );
  553. m_ch4So2Button->setChecked( false );
  554. m_ch4So2Button->move( 148, 51 + 3*12 );
  555. m_ch4So2Button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( "btn_on" ) );
  556. m_ch4So2Button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap("btn_off") );
  557. ToolTip::add( m_ch4So2Button, tr( "Channel4 to SO2 (Left)" ) );
  558. m_graph = new Graph( this );
  559. m_graph->setGraphStyle( Graph::NearestStyle );
  560. m_graph->setGraphColor( QColor(0x4E, 0x83, 0x2B) );
  561. m_graph->move( 37, 199 );
  562. m_graph->resize(208, 47);
  563. ToolTip::add( m_graph, tr( "Wave Pattern" ) );
  564. m_graph->setWhatsThis( tr( "Draw the wave here" ) );
  565. }
  566. papuInstrumentView::~papuInstrumentView()
  567. {
  568. }
  569. void papuInstrumentView::modelChanged()
  570. {
  571. papuInstrument * p = castModel<papuInstrument>();
  572. m_ch1SweepTimeKnob->setModel( &p->m_ch1SweepTimeModel );
  573. m_ch1SweepDirButton->setModel( &p->m_ch1SweepDirModel );
  574. m_ch1SweepRtShiftKnob->setModel( &p->m_ch1SweepRtShiftModel );
  575. m_ch1WavePatternDutyKnob->setModel( &p->m_ch1WavePatternDutyModel );
  576. m_ch1VolumeKnob->setModel( &p->m_ch1VolumeModel );
  577. m_ch1VolSweepDirButton->setModel( &p->m_ch1VolSweepDirModel );
  578. m_ch1SweepStepLengthKnob->setModel( &p->m_ch1SweepStepLengthModel );
  579. m_ch2WavePatternDutyKnob->setModel( &p->m_ch2WavePatternDutyModel );
  580. m_ch2VolumeKnob->setModel( &p->m_ch2VolumeModel );
  581. m_ch2VolSweepDirButton->setModel( &p->m_ch2VolSweepDirModel );
  582. m_ch2SweepStepLengthKnob->setModel( &p->m_ch2SweepStepLengthModel );
  583. //m_ch3OnButton->setModel( &p->m_ch3OnModel );
  584. m_ch3VolumeKnob->setModel( &p->m_ch3VolumeModel );
  585. m_ch4VolumeKnob->setModel( &p->m_ch4VolumeModel );
  586. m_ch4VolSweepDirButton->setModel( &p->m_ch4VolSweepDirModel );
  587. m_ch4SweepStepLengthKnob->setModel( &p->m_ch4SweepStepLengthModel );
  588. m_ch4ShiftRegWidthButton->setModel( &p->m_ch4ShiftRegWidthModel );
  589. m_so1VolumeKnob->setModel( &p->m_so1VolumeModel );
  590. m_so2VolumeKnob->setModel( &p->m_so2VolumeModel );
  591. m_ch1So1Button->setModel( &p->m_ch1So1Model );
  592. m_ch2So1Button->setModel( &p->m_ch2So1Model );
  593. m_ch3So1Button->setModel( &p->m_ch3So1Model );
  594. m_ch4So1Button->setModel( &p->m_ch4So1Model );
  595. m_ch1So2Button->setModel( &p->m_ch1So2Model );
  596. m_ch2So2Button->setModel( &p->m_ch2So2Model );
  597. m_ch3So2Button->setModel( &p->m_ch3So2Model );
  598. m_ch4So2Button->setModel( &p->m_ch4So2Model );
  599. m_trebleKnob->setModel( &p->m_trebleModel );
  600. m_bassKnob->setModel( &p->m_bassModel );
  601. m_graph->setModel( &p->m_graphModel );
  602. }
  603. extern "C"
  604. {
  605. // necessary for getting instance out of shared lib
  606. Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data )
  607. {
  608. return( new papuInstrument(
  609. static_cast<InstrumentTrack *>( _data ) ) );
  610. }
  611. }