vibed.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. /*
  2. * vibed.cpp - combination of PluckedStringSynth and BitInvader
  3. *
  4. * Copyright (c) 2006-2008 Danny McRae <khjklujn/at/yahoo/com>
  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 <QDomDocument>
  25. #include <QMap>
  26. #include <QWhatsThis>
  27. #include "vibed.h"
  28. #include "Engine.h"
  29. #include "InstrumentTrack.h"
  30. #include "Mixer.h"
  31. #include "NotePlayHandle.h"
  32. #include "ToolTip.h"
  33. #include "base64.h"
  34. #include "CaptionMenu.h"
  35. #include "Oscillator.h"
  36. #include "string_container.h"
  37. #include "templates.h"
  38. #include "volume.h"
  39. #include "Song.h"
  40. #include "embed.cpp"
  41. extern "C"
  42. {
  43. Plugin::Descriptor PLUGIN_EXPORT vibedstrings_plugin_descriptor =
  44. {
  45. STRINGIFY( PLUGIN_NAME ),
  46. "Vibed",
  47. QT_TRANSLATE_NOOP( "pluginBrowser",
  48. "Vibrating string modeler" ),
  49. "Danny McRae <khjklujn/at/yahoo/com>",
  50. 0x0100,
  51. Plugin::Instrument,
  52. new PluginPixmapLoader( "logo" ),
  53. NULL,
  54. NULL
  55. };
  56. }
  57. vibed::vibed( InstrumentTrack * _instrumentTrack ) :
  58. Instrument( _instrumentTrack, &vibedstrings_plugin_descriptor )
  59. {
  60. FloatModel * knob;
  61. BoolModel * led;
  62. nineButtonSelectorModel * harmonic;
  63. graphModel * graphTmp;
  64. for( int harm = 0; harm < 9; harm++ )
  65. {
  66. knob = new FloatModel( DefaultVolume, MinVolume, MaxVolume,
  67. 1.0f, this, tr( "String %1 volume" ).arg( harm+1 ) );
  68. m_volumeKnobs.append( knob );
  69. knob = new FloatModel( 0.0f, 0.0f, 0.05f, 0.001f, this,
  70. tr( "String %1 stiffness" ).arg( harm+1 ) );
  71. m_stiffnessKnobs.append( knob );
  72. knob = new FloatModel( 0.0f, 0.0f, 0.05f, 0.005f, this,
  73. tr( "Pick %1 position" ).arg( harm+1 ) );
  74. m_pickKnobs.append( knob );
  75. knob = new FloatModel( 0.05f, 0.0f, 0.05f, 0.005f, this,
  76. tr( "Pickup %1 position" ).arg( harm+1 ) );
  77. m_pickupKnobs.append( knob );
  78. knob = new FloatModel( 0.0f, -1.0f, 1.0f, 0.01f, this,
  79. tr( "Pan %1" ).arg( harm+1 ) );
  80. m_panKnobs.append( knob );
  81. knob = new FloatModel( 0.0f, -0.1f, 0.1f, 0.001f, this,
  82. tr( "Detune %1" ).arg( harm+1 ) );
  83. m_detuneKnobs.append( knob );
  84. knob = new FloatModel( 0.0f, 0.0f, 0.75f, 0.01f, this,
  85. tr( "Fuzziness %1 " ).arg( harm+1 ) );
  86. m_randomKnobs.append( knob );
  87. knob = new FloatModel( 1, 1, 16, 1, this,
  88. tr( "Length %1" ).arg( harm+1 ) );
  89. m_lengthKnobs.append( knob );
  90. led = new BoolModel( false, this,
  91. tr( "Impulse %1" ).arg( harm+1 ) );
  92. m_impulses.append( led );
  93. led = new BoolModel( harm==0, this,
  94. tr( "Octave %1" ).arg( harm+1 ) );
  95. m_powerButtons.append( led );
  96. harmonic = new nineButtonSelectorModel( 2, 0, 8, this );
  97. m_harmonics.append( harmonic );
  98. graphTmp = new graphModel( -1.0, 1.0, __sampleLength, this );
  99. graphTmp->setWaveToSine();
  100. m_graphs.append( graphTmp );
  101. }
  102. }
  103. vibed::~vibed()
  104. {
  105. }
  106. void vibed::saveSettings( QDomDocument & _doc, QDomElement & _this )
  107. {
  108. QString name;
  109. // Save plugin version
  110. _this.setAttribute( "version", "0.1" );
  111. for( int i = 0; i < 9; i++ )
  112. {
  113. name = "active" + QString::number( i );
  114. _this.setAttribute( name, QString::number(
  115. m_powerButtons[i]->value() ) );
  116. if( m_powerButtons[i]->value() )
  117. {
  118. name = "volume" + QString::number( i );
  119. m_volumeKnobs[i]->saveSettings( _doc, _this, name );
  120. name = "stiffness" + QString::number( i );
  121. m_stiffnessKnobs[i]->saveSettings( _doc, _this, name );
  122. name = "pick" + QString::number( i );
  123. m_pickKnobs[i]->saveSettings( _doc, _this, name );
  124. name = "pickup" + QString::number( i );
  125. m_pickupKnobs[i]->saveSettings( _doc, _this, name );
  126. name = "octave" + QString::number( i );
  127. m_harmonics[i]->saveSettings( _doc, _this, name );
  128. name = "length" + QString::number( i );
  129. m_lengthKnobs[i]->saveSettings( _doc, _this, name );
  130. name = "pan" + QString::number( i );
  131. m_panKnobs[i]->saveSettings( _doc, _this, name );
  132. name = "detune" + QString::number( i );
  133. m_detuneKnobs[i]->saveSettings( _doc, _this, name );
  134. name = "slap" + QString::number( i );
  135. m_randomKnobs[i]->saveSettings( _doc, _this, name );
  136. name = "impulse" + QString::number( i );
  137. m_impulses[i]->saveSettings( _doc, _this, name );
  138. QString sampleString;
  139. base64::encode(
  140. (const char *)m_graphs[i]->samples(),
  141. __sampleLength * sizeof(float),
  142. sampleString );
  143. name = "graph" + QString::number( i );
  144. _this.setAttribute( name, sampleString );
  145. }
  146. }
  147. }
  148. void vibed::loadSettings( const QDomElement & _this )
  149. {
  150. QString name;
  151. for( int i = 0; i < 9; i++ )
  152. {
  153. name = "active" + QString::number( i );
  154. m_powerButtons[i]->setValue( _this.attribute( name ).toInt() );
  155. if( m_powerButtons[i]->value() &&
  156. _this.hasAttribute( "volume" + QString::number( i ) ) )
  157. {
  158. name = "volume" + QString::number( i );
  159. m_volumeKnobs[i]->loadSettings( _this, name );
  160. name = "stiffness" + QString::number( i );
  161. m_stiffnessKnobs[i]->loadSettings( _this, name );
  162. name = "pick" + QString::number( i );
  163. m_pickKnobs[i]->loadSettings( _this, name );
  164. name = "pickup" + QString::number( i );
  165. m_pickupKnobs[i]->loadSettings( _this, name );
  166. name = "octave" + QString::number( i );
  167. m_harmonics[i]->loadSettings( _this, name );
  168. name = "length" + QString::number( i );
  169. m_lengthKnobs[i]->loadSettings( _this, name );
  170. name = "pan" + QString::number( i );
  171. m_panKnobs[i]->loadSettings( _this, name );
  172. name = "detune" + QString::number( i );
  173. m_detuneKnobs[i]->loadSettings( _this, name );
  174. name = "slap" + QString::number( i );
  175. m_randomKnobs[i]->loadSettings( _this, name );
  176. name = "impulse" + QString::number( i );
  177. m_impulses[i]->loadSettings( _this, name );
  178. int size = 0;
  179. float * shp = 0;
  180. base64::decode( _this.attribute( "graph" +
  181. QString::number( i ) ),
  182. &shp,
  183. &size );
  184. // TODO: check whether size == 128 * sizeof( float ),
  185. // otherwise me might and up in a segfault
  186. m_graphs[i]->setSamples( shp );
  187. delete[] shp;
  188. // TODO: do one of the following to avoid
  189. // "uninitialized" wave-shape-buttongroup
  190. // - activate random-wave-shape-button here
  191. // - make wave-shape-buttons simple toggle-buttons
  192. // instead of checkable buttons
  193. // - save and restore selected wave-shape-button
  194. }
  195. }
  196. // update();
  197. }
  198. QString vibed::nodeName() const
  199. {
  200. return( vibedstrings_plugin_descriptor.name );
  201. }
  202. void vibed::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer )
  203. {
  204. if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL )
  205. {
  206. _n->m_pluginData = new stringContainer( _n->frequency(),
  207. Engine::mixer()->processingSampleRate(),
  208. __sampleLength );
  209. for( int i = 0; i < 9; ++i )
  210. {
  211. if( m_powerButtons[i]->value() )
  212. {
  213. static_cast<stringContainer*>(
  214. _n->m_pluginData )->addString(
  215. m_harmonics[i]->value(),
  216. m_pickKnobs[i]->value(),
  217. m_pickupKnobs[i]->value(),
  218. m_graphs[i]->samples(),
  219. m_randomKnobs[i]->value(),
  220. m_stiffnessKnobs[i]->value(),
  221. m_detuneKnobs[i]->value(),
  222. static_cast<int>(
  223. m_lengthKnobs[i]->value() ),
  224. m_impulses[i]->value(),
  225. i );
  226. }
  227. }
  228. }
  229. const fpp_t frames = _n->framesLeftForCurrentPeriod();
  230. const f_cnt_t offset = _n->noteOffset();
  231. stringContainer * ps = static_cast<stringContainer *>(
  232. _n->m_pluginData );
  233. for( fpp_t i = offset; i < frames + offset; ++i )
  234. {
  235. _working_buffer[i][0] = 0.0f;
  236. _working_buffer[i][1] = 0.0f;
  237. int s = 0;
  238. for( int string = 0; string < 9; ++string )
  239. {
  240. if( ps->exists( string ) )
  241. {
  242. // pan: 0 -> left, 1 -> right
  243. const float pan = ( m_panKnobs[string]->value() + 1 ) / 2.0f;
  244. const sample_t sample = ps->getStringSample( s ) * m_volumeKnobs[string]->value() / 100.0f;
  245. _working_buffer[i][0] += ( 1.0f - pan ) * sample;
  246. _working_buffer[i][1] += pan * sample;
  247. s++;
  248. }
  249. }
  250. }
  251. instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n );
  252. }
  253. void vibed::deleteNotePluginData( NotePlayHandle * _n )
  254. {
  255. delete static_cast<stringContainer *>( _n->m_pluginData );
  256. }
  257. PluginView * vibed::instantiateView( QWidget * _parent )
  258. {
  259. return( new vibedView( this, _parent ) );
  260. }
  261. vibedView::vibedView( Instrument * _instrument,
  262. QWidget * _parent ) :
  263. InstrumentView( _instrument, _parent )
  264. {
  265. setAutoFillBackground( true );
  266. QPalette pal;
  267. pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(
  268. "artwork" ) );
  269. setPalette( pal );
  270. m_volumeKnob = new Knob( knobBright_26, this );
  271. m_volumeKnob->setVolumeKnob( true );
  272. m_volumeKnob->move( 103, 142 );
  273. m_volumeKnob->setHintText( tr( "Volume:" ), "" );
  274. m_volumeKnob->setWhatsThis( tr( "The 'V' knob sets the volume "
  275. "of the selected string." ) );
  276. m_stiffnessKnob = new Knob( knobBright_26, this );
  277. m_stiffnessKnob->move( 129, 142 );
  278. m_stiffnessKnob->setHintText( tr( "String stiffness:" )
  279. , "" );
  280. m_stiffnessKnob->setWhatsThis( tr(
  281. "The 'S' knob sets the stiffness of the selected string. The stiffness "
  282. "of the string affects how long the string will ring out. The lower "
  283. "the setting, the longer the string will ring." ) );
  284. m_pickKnob = new Knob( knobBright_26, this );
  285. m_pickKnob->move( 153, 142 );
  286. m_pickKnob->setHintText( tr( "Pick position:" ), "" );
  287. m_pickKnob->setWhatsThis( tr(
  288. "The 'P' knob sets the position where the selected string will be 'picked'. "
  289. "The lower the setting the closer the pick is to the bridge." ) );
  290. m_pickupKnob = new Knob( knobBright_26, this );
  291. m_pickupKnob->move( 177, 142 );
  292. m_pickupKnob->setHintText( tr( "Pickup position:" )
  293. , "" );
  294. m_pickupKnob->setWhatsThis( tr(
  295. "The 'PU' knob sets the position where the vibrations will be monitored "
  296. "for the selected string. The lower the setting, the closer the "
  297. "pickup is to the bridge." ) );
  298. m_panKnob = new Knob( knobBright_26, this );
  299. m_panKnob->move( 105, 187 );
  300. m_panKnob->setHintText( tr( "Pan:" ), "" );
  301. m_panKnob->setWhatsThis( tr(
  302. "The Pan knob determines the location of the selected string in the stereo "
  303. "field." ) );
  304. m_detuneKnob = new Knob( knobBright_26, this );
  305. m_detuneKnob->move( 150, 187 );
  306. m_detuneKnob->setHintText( tr( "Detune:" ), "" );
  307. m_detuneKnob->setWhatsThis( tr(
  308. "The Detune knob modifies the pitch of the selected string. Settings less "
  309. "than zero will cause the string to sound flat. Settings greater than zero "
  310. "will cause the string to sound sharp." ) );
  311. m_randomKnob = new Knob( knobBright_26, this );
  312. m_randomKnob->move( 194, 187 );
  313. m_randomKnob->setHintText( tr( "Fuzziness:" )
  314. , "" );
  315. m_randomKnob->setWhatsThis( tr(
  316. "The Slap knob adds a bit of fuzz to the selected string which is most "
  317. "apparent during the attack, though it can also be used to make the string "
  318. "sound more 'metallic'.") );
  319. m_lengthKnob = new Knob( knobBright_26, this );
  320. m_lengthKnob->move( 23, 193 );
  321. m_lengthKnob->setHintText( tr( "Length:" )
  322. , "" );
  323. m_lengthKnob->setWhatsThis( tr(
  324. "The Length knob sets the length of the selected string. Longer strings "
  325. "will both ring longer and sound brighter, however, they will also eat up "
  326. "more CPU cycles." ) );
  327. m_impulse = new LedCheckBox( "", this );
  328. m_impulse->move( 23, 94 );
  329. ToolTip::add( m_impulse,
  330. tr( "Impulse or initial state" ) );
  331. m_impulse->setWhatsThis( tr(
  332. "The 'Imp' selector determines whether the waveform in the graph is to be "
  333. "treated as an impulse imparted to the string by the pick or the initial "
  334. "state of the string." ) );
  335. m_harmonic = new nineButtonSelector(
  336. PLUGIN_NAME::getIconPixmap( "button_-2_on" ),
  337. PLUGIN_NAME::getIconPixmap( "button_-2_off" ),
  338. PLUGIN_NAME::getIconPixmap( "button_-1_on" ),
  339. PLUGIN_NAME::getIconPixmap( "button_-1_off" ),
  340. PLUGIN_NAME::getIconPixmap( "button_f_on" ),
  341. PLUGIN_NAME::getIconPixmap( "button_f_off" ),
  342. PLUGIN_NAME::getIconPixmap( "button_2_on" ),
  343. PLUGIN_NAME::getIconPixmap( "button_2_off" ),
  344. PLUGIN_NAME::getIconPixmap( "button_3_on" ),
  345. PLUGIN_NAME::getIconPixmap( "button_3_off" ),
  346. PLUGIN_NAME::getIconPixmap( "button_4_on" ),
  347. PLUGIN_NAME::getIconPixmap( "button_4_off" ),
  348. PLUGIN_NAME::getIconPixmap( "button_5_on" ),
  349. PLUGIN_NAME::getIconPixmap( "button_5_off" ),
  350. PLUGIN_NAME::getIconPixmap( "button_6_on" ),
  351. PLUGIN_NAME::getIconPixmap( "button_6_off" ),
  352. PLUGIN_NAME::getIconPixmap( "button_7_on" ),
  353. PLUGIN_NAME::getIconPixmap( "button_7_off" ),
  354. 2,
  355. 21, 127,
  356. this );
  357. m_harmonic->setWindowTitle( tr( "Octave" ) );
  358. m_harmonic->setWhatsThis( tr(
  359. "The Octave selector is used to choose which harmonic of the note the "
  360. "string will ring at. For example, '-2' means the string will ring two "
  361. "octaves below the fundamental, 'F' means the string will ring at the "
  362. "fundamental, and '6' means the string will ring six octaves above the "
  363. "fundamental." ) );
  364. m_stringSelector = new nineButtonSelector(
  365. PLUGIN_NAME::getIconPixmap( "button_1_on" ),
  366. PLUGIN_NAME::getIconPixmap( "button_1_off" ),
  367. PLUGIN_NAME::getIconPixmap( "button_2_on" ),
  368. PLUGIN_NAME::getIconPixmap( "button_2_off" ),
  369. PLUGIN_NAME::getIconPixmap( "button_3_on" ),
  370. PLUGIN_NAME::getIconPixmap( "button_3_off" ),
  371. PLUGIN_NAME::getIconPixmap( "button_4_on" ),
  372. PLUGIN_NAME::getIconPixmap( "button_4_off" ),
  373. PLUGIN_NAME::getIconPixmap( "button_5_on" ),
  374. PLUGIN_NAME::getIconPixmap( "button_5_off" ),
  375. PLUGIN_NAME::getIconPixmap( "button_6_on" ),
  376. PLUGIN_NAME::getIconPixmap( "button_6_off" ),
  377. PLUGIN_NAME::getIconPixmap( "button_7_on" ),
  378. PLUGIN_NAME::getIconPixmap( "button_7_off" ),
  379. PLUGIN_NAME::getIconPixmap( "button_8_on" ),
  380. PLUGIN_NAME::getIconPixmap( "button_8_off" ),
  381. PLUGIN_NAME::getIconPixmap( "button_9_on" ),
  382. PLUGIN_NAME::getIconPixmap( "button_9_off" ),
  383. 0,
  384. 21, 39,
  385. this);
  386. m_graph = new Graph( this );
  387. m_graph->setWindowTitle( tr( "Impulse Editor" ) );
  388. m_graph->setForeground( PLUGIN_NAME::getIconPixmap( "wavegraph4" ) );
  389. m_graph->move( 76, 21 );
  390. m_graph->resize(132, 104);
  391. m_graph->setWhatsThis( tr(
  392. "The waveform editor provides control over the initial state or impulse "
  393. "that is used to start the string vibrating. The buttons to the right of "
  394. "the graph will initialize the waveform to the selected type. The '?' "
  395. "button will load a waveform from a file--only the first 128 samples "
  396. "will be loaded.\n\n"
  397. "The waveform can also be drawn in the graph.\n\n"
  398. "The 'S' button will smooth the waveform.\n\n"
  399. "The 'N' button will normalize the waveform.") );
  400. setWhatsThis( tr(
  401. "Vibed models up to nine independently vibrating strings. The 'String' "
  402. "selector allows you to choose which string is being edited. The 'Imp' " "selector chooses whether the graph represents an impulse or the initial "
  403. "state of the string. The 'Octave' selector chooses which harmonic the "
  404. "string should vibrate at.\n\n"
  405. "The graph allows you to control the initial state or impulse used to set the "
  406. "string in motion.\n\n"
  407. "The 'V' knob controls the volume. The 'S' knob controls the string's "
  408. "stiffness. The 'P' knob controls the pick position. The 'PU' knob "
  409. "controls the pickup position.\n\n"
  410. "'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob "
  411. "adds a bit of fuzz to the sound of the string.\n\n"
  412. "The 'Length' knob controls the length of the string.\n\n"
  413. "The LED in the lower right corner of the waveform editor determines "
  414. "whether the string is active in the current instrument." ) );
  415. m_power = new LedCheckBox( "", this, tr( "Enable waveform" ) );
  416. m_power->move( 212, 130 );
  417. ToolTip::add( m_power,
  418. tr( "Click here to enable/disable waveform." ) );
  419. // String selector is not a part of the model
  420. m_stringSelector->setWindowTitle( tr( "String" ) );
  421. m_stringSelector->setWhatsThis( tr(
  422. "The String selector is used to choose which string the controls are "
  423. "editing. A Vibed instrument can contain up to nine independently "
  424. "vibrating strings. The LED in the lower right corner of the "
  425. "waveform editor indicates whether the selected string is active." ) );
  426. connect( m_stringSelector, SIGNAL( nineButtonSelection( int ) ),
  427. this, SLOT( showString( int ) ) );
  428. showString( 0 );
  429. m_sinWaveBtn = new PixmapButton( this, tr( "Sine wave" ) );
  430. m_sinWaveBtn->move( 212, 24 );
  431. m_sinWaveBtn->setActiveGraphic( embed::getIconPixmap(
  432. "sin_wave_active" ) );
  433. m_sinWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  434. "sin_wave_inactive" ) );
  435. ToolTip::add( m_sinWaveBtn,
  436. tr( "Use a sine-wave for "
  437. "current oscillator." ) );
  438. connect( m_sinWaveBtn, SIGNAL (clicked () ),
  439. this, SLOT ( sinWaveClicked() ) );
  440. m_triangleWaveBtn = new PixmapButton( this, tr( "Triangle wave" ) );
  441. m_triangleWaveBtn->move( 212, 41 );
  442. m_triangleWaveBtn->setActiveGraphic(
  443. embed::getIconPixmap( "triangle_wave_active" ) );
  444. m_triangleWaveBtn->setInactiveGraphic(
  445. embed::getIconPixmap( "triangle_wave_inactive" ) );
  446. ToolTip::add( m_triangleWaveBtn,
  447. tr( "Use a triangle-wave "
  448. "for current oscillator." ) );
  449. connect( m_triangleWaveBtn, SIGNAL ( clicked () ),
  450. this, SLOT ( triangleWaveClicked( ) ) );
  451. m_sawWaveBtn = new PixmapButton( this, tr( "Saw wave" ) );
  452. m_sawWaveBtn->move( 212, 58 );
  453. m_sawWaveBtn->setActiveGraphic( embed::getIconPixmap(
  454. "saw_wave_active" ) );
  455. m_sawWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  456. "saw_wave_inactive" ) );
  457. ToolTip::add( m_sawWaveBtn,
  458. tr( "Use a saw-wave for "
  459. "current oscillator." ) );
  460. connect( m_sawWaveBtn, SIGNAL (clicked () ),
  461. this, SLOT ( sawWaveClicked() ) );
  462. m_sqrWaveBtn = new PixmapButton( this, tr( "Square wave" ) );
  463. m_sqrWaveBtn->move( 212, 75 );
  464. m_sqrWaveBtn->setActiveGraphic( embed::getIconPixmap(
  465. "square_wave_active" ) );
  466. m_sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  467. "square_wave_inactive" ) );
  468. ToolTip::add( m_sqrWaveBtn,
  469. tr( "Use a square-wave for "
  470. "current oscillator." ) );
  471. connect( m_sqrWaveBtn, SIGNAL ( clicked () ),
  472. this, SLOT ( sqrWaveClicked() ) );
  473. m_whiteNoiseWaveBtn = new PixmapButton( this, tr( "White noise wave" ) );
  474. m_whiteNoiseWaveBtn->move( 212, 92 );
  475. m_whiteNoiseWaveBtn->setActiveGraphic(
  476. embed::getIconPixmap( "white_noise_wave_active" ) );
  477. m_whiteNoiseWaveBtn->setInactiveGraphic(
  478. embed::getIconPixmap( "white_noise_wave_inactive" ) );
  479. ToolTip::add( m_whiteNoiseWaveBtn,
  480. tr( "Use white-noise for "
  481. "current oscillator." ) );
  482. connect( m_whiteNoiseWaveBtn, SIGNAL ( clicked () ),
  483. this, SLOT ( noiseWaveClicked() ) );
  484. m_usrWaveBtn = new PixmapButton( this, tr( "User defined wave" ) );
  485. m_usrWaveBtn->move( 212, 109 );
  486. m_usrWaveBtn->setActiveGraphic( embed::getIconPixmap(
  487. "usr_wave_active" ) );
  488. m_usrWaveBtn->setInactiveGraphic( embed::getIconPixmap(
  489. "usr_wave_inactive" ) );
  490. ToolTip::add( m_usrWaveBtn,
  491. tr( "Use a user-defined "
  492. "waveform for current oscillator." ) );
  493. connect( m_usrWaveBtn, SIGNAL ( clicked () ),
  494. this, SLOT ( usrWaveClicked() ) );
  495. m_smoothBtn = new PixmapButton( this, tr( "Smooth" ) );
  496. m_smoothBtn->move( 79, 129 );
  497. m_smoothBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
  498. "smooth_active" ) );
  499. m_smoothBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
  500. "smooth_inactive" ) );
  501. m_smoothBtn->setChecked( false );
  502. ToolTip::add( m_smoothBtn,
  503. tr( "Click here to smooth waveform." ) );
  504. connect( m_smoothBtn, SIGNAL ( clicked () ),
  505. this, SLOT ( smoothClicked() ) );
  506. m_normalizeBtn = new PixmapButton( this, tr( "Normalize" ) );
  507. m_normalizeBtn->move( 96, 129 );
  508. m_normalizeBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
  509. "normalize_active" ) );
  510. m_normalizeBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
  511. "normalize_inactive" ) );
  512. m_normalizeBtn->setChecked( false );
  513. ToolTip::add( m_normalizeBtn,
  514. tr( "Click here to normalize waveform." ) );
  515. connect( m_normalizeBtn, SIGNAL ( clicked () ),
  516. this, SLOT ( normalizeClicked() ) );
  517. }
  518. void vibedView::modelChanged()
  519. {
  520. showString( 0 );
  521. }
  522. void vibedView::showString( int _string )
  523. {
  524. vibed * v = castModel<vibed>();
  525. m_pickKnob->setModel( v->m_pickKnobs[_string] );
  526. m_pickupKnob->setModel( v->m_pickupKnobs[_string] );
  527. m_stiffnessKnob->setModel( v->m_stiffnessKnobs[_string] );
  528. m_volumeKnob->setModel( v->m_volumeKnobs[_string] );
  529. m_panKnob->setModel( v->m_panKnobs[_string] );
  530. m_detuneKnob->setModel( v->m_detuneKnobs[_string] );
  531. m_randomKnob->setModel( v->m_randomKnobs[_string] );
  532. m_lengthKnob->setModel( v->m_lengthKnobs[_string] );
  533. m_graph->setModel( v->m_graphs[_string] );
  534. m_impulse->setModel( v->m_impulses[_string] );
  535. m_harmonic->setModel( v->m_harmonics[_string] );
  536. m_power->setModel( v->m_powerButtons[_string] );
  537. }
  538. void vibedView::sinWaveClicked()
  539. {
  540. m_graph->model()->setWaveToSine();
  541. Engine::getSong()->setModified();
  542. }
  543. void vibedView::triangleWaveClicked()
  544. {
  545. m_graph->model()->setWaveToTriangle();
  546. Engine::getSong()->setModified();
  547. }
  548. void vibedView::sawWaveClicked()
  549. {
  550. m_graph->model()->setWaveToSaw();
  551. Engine::getSong()->setModified();
  552. }
  553. void vibedView::sqrWaveClicked()
  554. {
  555. m_graph->model()->setWaveToSquare();
  556. Engine::getSong()->setModified();
  557. }
  558. void vibedView::noiseWaveClicked()
  559. {
  560. m_graph->model()->setWaveToNoise();
  561. Engine::getSong()->setModified();
  562. }
  563. void vibedView::usrWaveClicked()
  564. {
  565. QString fileName = m_graph->model()->setWaveToUser();
  566. ToolTip::add( m_usrWaveBtn, fileName );
  567. Engine::getSong()->setModified();
  568. }
  569. void vibedView::smoothClicked()
  570. {
  571. m_graph->model()->smooth();
  572. Engine::getSong()->setModified();
  573. }
  574. void vibedView::normalizeClicked()
  575. {
  576. m_graph->model()->normalize();
  577. Engine::getSong()->setModified();
  578. }
  579. void vibedView::contextMenuEvent( QContextMenuEvent * )
  580. {
  581. CaptionMenu contextMenu( model()->displayName(), this );
  582. contextMenu.addHelpAction();
  583. contextMenu.exec( QCursor::pos() );
  584. }
  585. void vibedView::displayHelp()
  586. {
  587. QWhatsThis::showText( mapToGlobal( rect().bottomRight() ),
  588. whatsThis() );
  589. }
  590. extern "C"
  591. {
  592. // necessary for getting instance out of shared lib
  593. Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data )
  594. {
  595. return( new vibed( static_cast<InstrumentTrack *>( _data ) ) );
  596. }
  597. }