From 5fb9afc15a15860991e82a3089a6e41c92e6f766 Mon Sep 17 00:00:00 2001 From: Wong Cho Ching Date: Sat, 25 Jan 2014 21:42:22 +0800 Subject: [PATCH] GUI Completed. --- data/themes/default/style.css | 8 + plugins/CMakeLists.txt | 1 + plugins/sfxr/CMakeLists.txt | 2 +- plugins/sfxr/artwork.png | Bin 44968 -> 27416 bytes plugins/sfxr/logo.png | Bin 1109 -> 433 bytes plugins/sfxr/sfxr.cpp | 943 +++++++++++++++++++++++----------- plugins/sfxr/sfxr.h | 214 ++++++-- 7 files changed, 811 insertions(+), 357 deletions(-) diff --git a/data/themes/default/style.css b/data/themes/default/style.css index 0d199ba12..5dde74977 100644 --- a/data/themes/default/style.css +++ b/data/themes/default/style.css @@ -472,6 +472,14 @@ sf2InstrumentView knob { qproperty-lineWidth: 2; } +sfxrInstrumentView knob { + color: #b06319; + qproperty-outerColor: rgb(194, 177, 145); + qproperty-innerRadius: 2; + qproperty-outerRadius: 10; + qproperty-lineWidth: 2; +} + opl2instrumentView knob { color: rgb(128,128,128); qproperty-outerColor: rgb(255,255,255); diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 0cbdc4359..6f315b792 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -15,6 +15,7 @@ ADD_SUBDIRECTORY(papu) ADD_SUBDIRECTORY(patman) ADD_SUBDIRECTORY(peak_controller_effect) ADD_SUBDIRECTORY(sf2_player) +ADD_SUBDIRECTORY(sfxr) ADD_SUBDIRECTORY(sid) ADD_SUBDIRECTORY(spectrum_analyzer) ADD_SUBDIRECTORY(stereo_enhancer) diff --git a/plugins/sfxr/CMakeLists.txt b/plugins/sfxr/CMakeLists.txt index 6d3f61a0c..2fe490d1e 100644 --- a/plugins/sfxr/CMakeLists.txt +++ b/plugins/sfxr/CMakeLists.txt @@ -1,3 +1,3 @@ INCLUDE(BuildPlugin) -BUILD_PLUGIN(sfxr sfxr.cpp sfxr.h MOCFILES EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) +BUILD_PLUGIN(sfxr sfxr.cpp sfxr.h MOCFILES sfxr.h EMBEDDED_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.png) diff --git a/plugins/sfxr/artwork.png b/plugins/sfxr/artwork.png index 3938592ca936dde89545f1d2f63b67ccbc74669c..15f313d45f52d47f57f1de11380a09affc5216da 100644 GIT binary patch literal 27416 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

w+8L9Xn#y$vks44R_3 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 MPF=QA+9LRW06|YJcmMzZ literal 44968 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 C7=(xb diff --git a/plugins/sfxr/logo.png b/plugins/sfxr/logo.png index 2e84cba5a1377f9a65f4b1db243846c05b713dab..a39e4e86572cd008bf410ed2c308453db3132261 100644 GIT binary patch delta 287 zcmV+)0pR}C2(bf@BxS%*OjJd$t*?xamH718s-lQUL^xGXK*hC_#)5g1&8X49oyoYDysV833kkokkhrOfx2TJ#n}D;Ug_w$Q!m*Lex|uaECHl#hhIVD& zt$uA)KH;!}W?4;>4h^XtZ-B^DsW~L5N#ijqE?5`ftscOqGytfGvcGu# z1F1)XdCdl}j&)H0D;iRS5hL=Y2?{fNWxUO_X5`$sO7JUcgF>hwupxlE>GWD3E2b&a lnHpA>R6kD|>-}XN1O~+D(&1t;wyyvH002ovPDHLkV1mqXhRpx~ delta 817 zcmV-11J3-h1JwwSBnkm@Qb$4nuFf3kk@_AI*a-m_6)c+(4)g#30Rm7=R7H`ISdpMf zk)TPDpcQ}r|Ns8*;H&@u0915RPE!B@0s{mE1_uZU3=Iws5E2s>7Z@5F9337XAR!|p zB_<~+Dl9H9FfubXH#|K)LqDVw zprtV%du9Lt00Cl4M?_VV1h_K*00L}DL_t(Y$Gv}+Yh#))6ow@r0wboKn-ee48&c~f ztGBk((QYzb?Yg#``~QDs1dt>suzl(I;N^tJW0I5iO`-5=A;j@dc>#!0F$hTnLVg~I zva0FO4_#Ab5#;3sQGpesXT!$}ezBFGfHSnjA1auj-1TS2^I@(1aAQIN;02)At7l?@l>jHL@UIAsX~wA3hD7 zlM`nUCrB)r3gH|!-1ts{odaE^4B&H*u9APh5BBJ8oeundUf+%AK9HTRIe13rNF&U> z+|RIM#5+xT3DwSUI`H!r+ciXcNdU5TXm-O+p6hWOjl$q0$4@}w>mFbIo!0mq< z8tJ?i?TNHGgl`^hLFV-21Ej;5(~}RZ#@7D=M@b;1mtGODAgch`M>J9zRsnJWq5}z? z%m(H?veQHXF6WEY`Y}TUULM!0#hmDI(5)ZNx_Er!aze*_dj9U-jB$@B{?<**<3Q+A zfQQ+@IW_}N+4>Sh2`SwXTLfd*3Y>kfq*tA(x7icFo;)JwCDs>xQw61Ry>qn>cv@T& z!vG2AO&Sif`q!Z)C7nGGkIuyPmMbQfo*S9o?p=V$Q@!2C!!Z*>+^4p>r-r}4E$fI0 vt3?)b-|zFrPlLY#?A%b|s|5}Il2P~zO&!0VB_!@h00000NkvXXu0mjfP~B|g diff --git a/plugins/sfxr/sfxr.cpp b/plugins/sfxr/sfxr.cpp index 246e9a907..2e942a6ab 100644 --- a/plugins/sfxr/sfxr.cpp +++ b/plugins/sfxr/sfxr.cpp @@ -1,5 +1,6 @@ /* * sfxr.cpp - port of sfxr to LMMS + * The original readme file of sfxr can be found in readme.txt in this directory. * * Copyright (c) 2014 Wong Cho Ching * @@ -19,9 +20,19 @@ * License along with this program (see COPYING); if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. - * */ +#include + +#define rnd(n) (rand()%(n+1)) + +#define PI 3.14159265f + +float frnd(float range) +{ + return (float)rnd(10000)/10000*range; +} + #include @@ -43,7 +54,7 @@ extern "C" { -Plugin::Descriptor PLUGIN_EXPORT bitinvader_plugin_descriptor = +Plugin::Descriptor PLUGIN_EXPORT sfxr_plugin_descriptor = { STRINGIFY( PLUGIN_NAME ), "sfxr", @@ -60,7 +71,7 @@ Plugin::Descriptor PLUGIN_EXPORT bitinvader_plugin_descriptor = } -bSynth::bSynth( float * _shape, int _length, notePlayHandle * _nph, bool _interpolation, +SfxrSynth::SfxrSynth( float * _shape, int _length, notePlayHandle * _nph, bool _interpolation, float _factor, const sample_rate_t _sample_rate ) : sample_index( 0 ), sample_realindex( 0 ), @@ -77,18 +88,18 @@ bSynth::bSynth( float * _shape, int _length, notePlayHandle * _nph, bool _interp } -bSynth::~bSynth() +SfxrSynth::~SfxrSynth() { delete[] sample_shape; } -sample_t bSynth::nextStringSample() +sample_t SfxrSynth::nextStringSample() { - float sample_step = + float sample_step = static_cast( sample_length / ( sample_rate / nph->frequency() ) ); - + // check overflow while (sample_realindex >= sample_length) { sample_realindex -= sample_length; @@ -98,168 +109,195 @@ sample_t bSynth::nextStringSample() if (interpolation) { - // find position in shape - int a = static_cast(sample_realindex); + // find position in shape + int a = static_cast(sample_realindex); int b; if (a < (sample_length-1)) { b = static_cast(sample_realindex+1); } else { b = 0; } - + // Nachkommaanteil float frac = sample_realindex - static_cast(sample_realindex); - + sample = sample_shape[a]*(1-frac) + sample_shape[b]*(frac); } else { // No interpolation - sample_index = static_cast(sample_realindex); + sample_index = static_cast(sample_realindex); sample = sample_shape[sample_index]; } - + // progress in shape sample_realindex += sample_step; return sample; -} - -/*********************************************************************** -* -* class BitInvader -* -* lmms - plugin -* -***********************************************************************/ +} -bitInvader::bitInvader( InstrumentTrack * _instrument_track ) : - Instrument( _instrument_track, &bitinvader_plugin_descriptor ), - m_sampleLength( 128, 8, 128, 1, this, tr( "Samplelength" ) ), - m_graph( -1.0f, 1.0f, 128, this ), - m_interpolation( false, this ), - m_normalize( false, this ) + + +sfxrInstrument::sfxrInstrument( InstrumentTrack * _instrument_track ) : + Instrument( _instrument_track, &sfxr_plugin_descriptor ), + m_attModel(0.0f, this), + m_holdModel(0.3f, this), + m_susModel(0.0f, this), + m_decModel(0.4f, this), + + m_startFreqModel(0.3f, this), + m_minFreqModel(0.0f, this), + m_slideModel(0.0f, this), + m_dSlideModel(0.0f, this), + m_vibDepthModel(0.0f, this), + m_vibSpeedModel(0.0f, this), + + m_changeAmtModel(0.0f, this), + m_changeSpeedModel(0.0f, this), + + m_sqrDutyModel(0.0f, this), + m_sqrSweepModel(0.0f, this), + + m_repeatSpeedModel(0.0f, this), + + m_phaserOffsetModel(0.0f, this), + m_phaserSweepModel(0.0f, this), + + m_lpFilCutModel(1.0f, this), + m_lpFilCutSweepModel(0.0f, this), + m_lpFilResoModel(0.0f, this), + m_hpFilCutModel(0.0f, this), + m_hpFilCutSweepModel(0.0f, this), + m_waveFormModel( SQR_WAVE, 0, WAVES_NUM-1, this, tr( "Wave Form" ) ) { - - m_graph.setWaveToSine(); - + //TODO + /* connect( &m_sampleLength, SIGNAL( dataChanged( ) ), this, SLOT( lengthChanged( ) ) ); connect( &m_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( samplesChanged( int, int ) ) ); - + */ } -bitInvader::~bitInvader() +sfxrInstrument::~sfxrInstrument() { } -void bitInvader::saveSettings( QDomDocument & _doc, QDomElement & _this ) +void sfxrInstrument::saveSettings( QDomDocument & _doc, QDomElement & _this ) { + _this.setAttribute( "version", "1" ); + m_attModel.saveSettings( _doc, _this, "att" ); + m_holdModel.saveSettings( _doc, _this, "hold" ); + m_susModel.saveSettings( _doc, _this, "sus" ); + m_decModel.saveSettings( _doc, _this, "dec" ); - // Save plugin version - _this.setAttribute( "version", "0.1" ); + m_startFreqModel.saveSettings( _doc, _this, "startFreq" ); + m_minFreqModel.saveSettings( _doc, _this, "minFreq" ); + m_slideModel.saveSettings( _doc, _this, "slide" ); + m_dSlideModel.saveSettings( _doc, _this, "dSlide" ); + m_vibDepthModel.saveSettings( _doc, _this, "vibDepth" ); + m_vibSpeedModel.saveSettings( _doc, _this, "vibSpeed" ); - // Save sample length - m_sampleLength.saveSettings( _doc, _this, "sampleLength" ); + m_changeAmtModel.saveSettings( _doc, _this, "changeAmt" ); + m_changeSpeedModel.saveSettings( _doc, _this, "changeSpeed" ); - // Save sample shape base64-encoded - QString sampleString; - base64::encode( (const char *)m_graph.samples(), - m_graph.length() * sizeof(float), sampleString ); - _this.setAttribute( "sampleShape", sampleString ); - + m_sqrDutyModel.saveSettings( _doc, _this, "sqrDuty" ); + m_sqrSweepModel.saveSettings( _doc, _this, "sqrSweep" ); - // save LED normalize - m_interpolation.saveSettings( _doc, _this, "interpolation" ); - - // save LED - m_normalize.saveSettings( _doc, _this, "normalize" ); + m_repeatSpeedModel.saveSettings( _doc, _this, "repeatSpeed" ); + + m_phaserOffsetModel.saveSettings( _doc, _this, "phaserOffset" ); + m_phaserSweepModel.saveSettings( _doc, _this, "phaserSweep" ); + + m_lpFilCutModel.saveSettings( _doc, _this, "lpFilCut" ); + m_lpFilCutSweepModel.saveSettings( _doc, _this, "lpFilCutSweep" ); + m_lpFilResoModel.saveSettings( _doc, _this, "lpFilReso" ); + m_hpFilCutModel.saveSettings( _doc, _this, "hpFilCut" ); + m_hpFilCutSweepModel.saveSettings( _doc, _this, "hpFilCutSweep" ); + + m_waveFormModel.saveSettings( _doc, _this, "waveForm" ); } -void bitInvader::loadSettings( const QDomElement & _this ) +void sfxrInstrument::loadSettings( const QDomElement & _this ) { - // Load sample length - m_sampleLength.loadSettings( _this, "sampleLength" ); - int sampleLength = (int)m_sampleLength.value(); + m_attModel.loadSettings(_this, "att" ); + m_holdModel.loadSettings( _this, "hold" ); + m_susModel.loadSettings( _this, "sus" ); + m_decModel.loadSettings( _this, "dec" ); - // Load sample shape - int size = 0; - char * dst = 0; - base64::decode( _this.attribute( "sampleShape"), &dst, &size ); + m_startFreqModel.loadSettings( _this, "startFreq" ); + m_minFreqModel.loadSettings( _this, "minFreq" ); + m_slideModel.loadSettings( _this, "slide" ); + m_dSlideModel.loadSettings( _this, "dSlide" ); + m_vibDepthModel.loadSettings( _this, "vibDepth" ); + m_vibSpeedModel.loadSettings( _this, "vibSpeed" ); - m_graph.setLength( sampleLength ); - m_graph.setSamples( (float*) dst ); - delete[] dst; + m_changeAmtModel.loadSettings( _this, "changeAmt" ); + m_changeSpeedModel.loadSettings( _this, "changeSpeed" ); - // Load LED normalize - m_interpolation.loadSettings( _this, "interpolation" ); - // Load LED - m_normalize.loadSettings( _this, "normalize" ); + m_sqrDutyModel.loadSettings( _this, "sqrDuty" ); + m_sqrSweepModel.loadSettings( _this, "sqrSweep" ); + + m_repeatSpeedModel.loadSettings( _this, "repeatSpeed" ); + + m_phaserOffsetModel.loadSettings( _this, "phaserOffset" ); + m_phaserSweepModel.loadSettings( _this, "phaserSweep" ); + + m_lpFilCutModel.loadSettings( _this, "lpFilCut" ); + m_lpFilCutSweepModel.loadSettings( _this, "lpFilCutSweep" ); + m_lpFilResoModel.loadSettings( _this, "lpFilReso" ); + m_hpFilCutModel.loadSettings( _this, "hpFilCut" ); + m_hpFilCutSweepModel.loadSettings( _this, "hpFilCutSweep" ); + + m_waveFormModel.loadSettings( _this, "waveForm" ); } -void bitInvader::lengthChanged() +void sfxrInstrument::samplesChanged( int _begin, int _end ) { - m_graph.setLength( (int) m_sampleLength.value() ); - - normalize(); -} - - - - -void bitInvader::samplesChanged( int _begin, int _end ) -{ - normalize(); + //TODO + //normalize(); //engine::getSongEditor()->setModified(); } -void bitInvader::normalize() +QString sfxrInstrument::nodeName() const { - // analyze - float max = 0; - const float* samples = m_graph.samples(); - for(int i=0; i < m_graph.length(); i++) - { - const float f = fabsf( samples[i] ); - if (f > max) { max = f; } - } - m_normalizeFactor = 1.0 / max; + return( sfxr_plugin_descriptor.name ); } -QString bitInvader::nodeName() const +f_cnt_t sfxrInstrument::desiredReleaseFrames() const { - return( bitinvader_plugin_descriptor.name ); + //TODO: check whether this disables + return 0; } - -void bitInvader::playNote( notePlayHandle * _n, +void sfxrInstrument::playNote( notePlayHandle * _n, sampleFrame * _working_buffer ) { - if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL ) + //TODO + /*if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == NULL ) { float factor; @@ -272,7 +310,7 @@ void bitInvader::playNote( notePlayHandle * _n, factor = m_normalizeFactor; } - _n->m_pluginData = new bSynth( + _n->m_pluginData = new SfxrSynth( const_cast( m_graph.samples() ), m_graph.length(), _n, @@ -282,7 +320,7 @@ void bitInvader::playNote( notePlayHandle * _n, const fpp_t frames = _n->framesLeftForCurrentPeriod(); - bSynth * ps = static_cast( _n->m_pluginData ); + SfxrSynth * ps = static_cast( _n->m_pluginData ); for( fpp_t frame = 0; frame < frames; ++frame ) { const sample_t cur = ps->nextStringSample(); @@ -294,281 +332,588 @@ void bitInvader::playNote( notePlayHandle * _n, applyRelease( _working_buffer, _n ); - instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n ); + instrumentTrack()->processAudioBuffer( _working_buffer, frames, _n );*/ } -void bitInvader::deleteNotePluginData( notePlayHandle * _n ) +void sfxrInstrument::deleteNotePluginData( notePlayHandle * _n ) { - delete static_cast( _n->m_pluginData ); + delete static_cast( _n->m_pluginData ); } -PluginView * bitInvader::instantiateView( QWidget * _parent ) +PluginView * sfxrInstrument::instantiateView( QWidget * _parent ) { - return( new bitInvaderView( this, _parent ) ); + return( new sfxrInstrumentView( this, _parent ) ); } +void sfxrInstrument::resetModels() +{ + m_attModel.reset(); + m_holdModel.reset(); + m_susModel.reset(); + m_decModel.reset(); + + m_startFreqModel.reset(); + m_minFreqModel.reset(); + m_slideModel.reset(); + m_dSlideModel.reset(); + m_vibDepthModel.reset(); + m_vibSpeedModel.reset(); + + m_changeAmtModel.reset(); + m_changeSpeedModel.reset(); + + m_sqrDutyModel.reset(); + m_sqrSweepModel.reset(); + + m_repeatSpeedModel.reset(); + + m_phaserOffsetModel.reset(); + m_phaserSweepModel.reset(); + + m_lpFilCutModel.reset(); + m_lpFilCutSweepModel.reset(); + m_lpFilResoModel.reset(); + m_hpFilCutModel.reset(); + m_hpFilCutSweepModel.reset(); + + m_waveFormModel.reset(); +} -bitInvaderView::bitInvaderView( Instrument * _instrument, + +class sfxrKnob : public knob +{ +public: + sfxrKnob( QWidget * _parent ) : + knob( knobStyled, _parent ) + { + setFixedSize( 20, 20 ); + setCenterPointX( 10.0 ); + setCenterPointY( 10.0 ); + setTotalAngle( 270.0 ); + setLineWidth( 1 ); + } +}; + + + + +#define createKnob(_knob, _x, _y, _name)\ + _knob = new sfxrKnob( this ); \ + _knob->setHintText( tr( _name ":" ), "" ); \ + _knob->move( _x, _y ); \ + toolTip::add( _knob, tr( _name ) ); + + + + +#define createButton(_button, _x, _y, _name, _resName)\ + _button = new pixmapButton( this, tr( "Sine wave" ) );\ + _button->move( _x, _y );\ + _button->setActiveGraphic( embed::getIconPixmap( _resName "_active" ) );\ + _button->setInactiveGraphic( embed::getIconPixmap( _resName "_inactive" ) );\ + toolTip::add( _button, tr( _name ) ); + + + + +#define createButtonLocalGraphic(_button, _x, _y, _name, _resName)\ + _button = new pixmapButton( this, tr( "Sine wave" ) );\ + _button->move( _x, _y );\ + _button->setActiveGraphic( PLUGIN_NAME::getIconPixmap( _resName "_active" ) );\ + _button->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( _resName "_inactive" ) );\ + toolTip::add( _button, tr( _name ) ); + + + + +sfxrInstrumentView::sfxrInstrumentView( Instrument * _instrument, QWidget * _parent ) : InstrumentView( _instrument, _parent ) { + srand(time(NULL)); setAutoFillBackground( true ); QPalette pal; - - pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( - "artwork" ) ); + pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) ); setPalette( pal ); - - m_sampleLengthKnob = new knob( knobDark_28, this ); - m_sampleLengthKnob->move( 10, 120 ); - m_sampleLengthKnob->setHintText( tr( "Sample Length" ) + " ", "" ); - m_graph = new graph( this, graph::NearestStyle ); - m_graph->move(53,118); // 55,120 - 2px border - m_graph->setAutoFillBackground( true ); + createKnob(m_attKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Attack Time"); + createKnob(m_holdKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Sustain Time"); + createKnob(m_susKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Sustain Punch"); + createKnob(m_decKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*0, "Decay Time"); - toolTip::add( m_graph, tr ( "Draw your own waveform here " - "by dragging your mouse on this graph." - )); + createKnob(m_startFreqKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Start Frequency"); + createKnob(m_minFreqKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Min Frequency"); + createKnob(m_slideKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Slide"); + createKnob(m_dSlideKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Delta Slide"); + createKnob(m_vibDepthKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*4, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Vibrato Depth"); + createKnob(m_vibSpeedKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*5, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*1, "Vibrato Speed"); + + createKnob(m_changeAmtKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Change Amount"); + createKnob(m_changeSpeedKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Change Speed"); + + createKnob(m_sqrDutyKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Squre Duty(Square wave only)"); + createKnob(m_sqrSpeedKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*4, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*2, "Squre Sweep(Square wave only)"); + + createKnob(m_repeatSpeedKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*3, "Repeat Speed"); + + createKnob(m_phaserOffsetKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*3, "Phaser Offset"); + createKnob(m_phaserSweepKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*3, "Phaser Sweep"); + + createKnob(m_lpFilCutKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*0, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "LP Filter Cutoff"); + createKnob(m_lpFilCutSweepKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*1, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "LP Filter Cutoff Sweep"); + createKnob(m_lpFilResoKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*2, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "LP Filter Resonance"); + createKnob(m_hpFilCutKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*3, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "HP Filter Cutoff"); + createKnob(m_hpFilCutSweepKnob, KNOBS_BASE_X+KNOB_BLOCK_SIZE_X*4, KNOBS_BASE_Y+KNOB_BLOCK_SIZE_Y*4, "HP Filter Cutoff Sweep"); + + createButton(m_sqrWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*0, WAVEFORM_BASE_Y, "Square Wave", "square_wave"); + createButton(m_sawWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*1, WAVEFORM_BASE_Y, "Saw Wave", "saw_wave"); + createButton(m_sinWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*2, WAVEFORM_BASE_Y, "Sine Wave", "sin_wave"); + createButton(m_noiseWaveBtn, KNOBS_BASE_X+WAVEFORM_BUTTON_WIDTH*3, WAVEFORM_BASE_Y, "Noise", "white_noise_wave"); + + m_waveBtnGroup = new automatableButtonGroup( this ); + m_waveBtnGroup->addButton(m_sqrWaveBtn); + m_waveBtnGroup->addButton(m_sawWaveBtn); + m_waveBtnGroup->addButton(m_sinWaveBtn); + m_waveBtnGroup->addButton(m_noiseWaveBtn); + connect( m_waveBtnGroup, SIGNAL ( dataChanged() ), + this, SLOT ( waveFormChanged() ) ); - pal = QPalette(); - pal.setBrush( backgroundRole(), - PLUGIN_NAME::getIconPixmap("wavegraph") ); - m_graph->setPalette( pal ); + createButtonLocalGraphic(m_pickupBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*0, GENERATOR_BASE_Y, "Generate pick up/coin sfx", "pickup"); + createButtonLocalGraphic(m_laserBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*1, GENERATOR_BASE_Y, "Generate laser/shoot sfx", "laser"); + createButtonLocalGraphic(m_explosionBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*2, GENERATOR_BASE_Y, "Generate explosion sfx", "explosion"); + createButtonLocalGraphic(m_powerupBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*3, GENERATOR_BASE_Y, "Generate power up sfx", "powerup"); + createButtonLocalGraphic(m_hitBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*4, GENERATOR_BASE_Y, "Generate hit/hurt sfx", "hit"); + createButtonLocalGraphic(m_jumpBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*5, GENERATOR_BASE_Y, "Generate jump sfx", "jump"); + createButtonLocalGraphic(m_blipBtn, GENERATOR_BASE_X+GENERATOR_BUTTON_WIDTH*6, GENERATOR_BASE_Y, "Generate blip/select sfx", "blip"); + connect( m_pickupBtn, SIGNAL ( clicked() ), this, SLOT ( genPickup() ) ); + connect( m_laserBtn, SIGNAL ( clicked() ), this, SLOT ( genLaser() ) ); + connect( m_explosionBtn, SIGNAL ( clicked() ), this, SLOT ( genExplosion() ) ); + connect( m_powerupBtn, SIGNAL ( clicked() ), this, SLOT ( genPowerup() ) ); + connect( m_hitBtn, SIGNAL ( clicked() ), this, SLOT ( genHit() ) ); + connect( m_jumpBtn, SIGNAL ( clicked() ), this, SLOT ( genJump() ) ); + connect( m_blipBtn, SIGNAL ( clicked() ), this, SLOT ( genBlip() ) ); - m_sinWaveBtn = new pixmapButton( this, tr( "Sine wave" ) ); - m_sinWaveBtn->move( 188, 120 ); - m_sinWaveBtn->setActiveGraphic( embed::getIconPixmap( - "sin_wave_active" ) ); - m_sinWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "sin_wave_inactive" ) ); - toolTip::add( m_sinWaveBtn, - tr( "Click for a sine-wave." ) ); + createButtonLocalGraphic(m_randomizeBtn, RAND_BUTTON_X, RAND_BUTTON_Y, "Generate random sfx", "randomize"); + createButtonLocalGraphic(m_mutateBtn, MUTA_BUTTON_X, MUTA_BUTTON_Y, "Mutate sfx", "mutate"); + connect( m_randomizeBtn, SIGNAL ( clicked() ), this, SLOT ( randomize() ) ); + connect( m_mutateBtn, SIGNAL ( clicked() ), this, SLOT ( mutate() ) ); - m_triangleWaveBtn = new pixmapButton( this, tr( "Triangle wave" ) ); - m_triangleWaveBtn->move( 188, 136 ); - m_triangleWaveBtn->setActiveGraphic( - embed::getIconPixmap( "triangle_wave_active" ) ); - m_triangleWaveBtn->setInactiveGraphic( - embed::getIconPixmap( "triangle_wave_inactive" ) ); - toolTip::add( m_triangleWaveBtn, - tr( "Click here for a triangle-wave." ) ); + //TODO: for each generator button: + /*connect( m_pickupBtn, SIGNAL ( dataChanged() ), + this, SLOT ( pickupClicked() ) );*/ - m_sawWaveBtn = new pixmapButton( this, tr( "Saw wave" ) ); - m_sawWaveBtn->move( 188, 152 ); - m_sawWaveBtn->setActiveGraphic( embed::getIconPixmap( - "saw_wave_active" ) ); - m_sawWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "saw_wave_inactive" ) ); - toolTip::add( m_sawWaveBtn, - tr( "Click here for a saw-wave." ) ); - - m_sqrWaveBtn = new pixmapButton( this, tr( "Square wave" ) ); - m_sqrWaveBtn->move( 188, 168 ); - m_sqrWaveBtn->setActiveGraphic( embed::getIconPixmap( - "square_wave_active" ) ); - m_sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "square_wave_inactive" ) ); - toolTip::add( m_sqrWaveBtn, - tr( "Click here for a square-wave." ) ); - - m_whiteNoiseWaveBtn = new pixmapButton( this, - tr( "White noise wave" ) ); - m_whiteNoiseWaveBtn->move( 188, 184 ); - m_whiteNoiseWaveBtn->setActiveGraphic( - embed::getIconPixmap( "white_noise_wave_active" ) ); - m_whiteNoiseWaveBtn->setInactiveGraphic( - embed::getIconPixmap( "white_noise_wave_inactive" ) ); - toolTip::add( m_whiteNoiseWaveBtn, - tr( "Click here for white-noise." ) ); - - m_usrWaveBtn = new pixmapButton( this, tr( "User defined wave" ) ); - m_usrWaveBtn->move( 188, 200 ); - m_usrWaveBtn->setActiveGraphic( embed::getIconPixmap( - "usr_wave_active" ) ); - m_usrWaveBtn->setInactiveGraphic( embed::getIconPixmap( - "usr_wave_inactive" ) ); - toolTip::add( m_usrWaveBtn, - tr( "Click here for a user-defined shape." ) ); - - m_smoothBtn = new pixmapButton( this, tr( "Smooth" ) ); - m_smoothBtn->move( 35, 200 ); - m_smoothBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap( - "smooth" ) ); - m_smoothBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap( - "smooth" ) ); - m_smoothBtn->setChecked( true ); - toolTip::add( m_smoothBtn, - tr( "Click here to smooth waveform." ) ); - - - m_interpolationToggle = new ledCheckBox( "Interpolation", this, - tr( "Interpolation" ) ); - m_interpolationToggle->move( 55,80 ); - - - m_normalizeToggle = new ledCheckBox( "Normalize", this, - tr( "Normalize" ) ); - m_normalizeToggle->move( 55, 100 ); - - - connect( m_sinWaveBtn, SIGNAL (clicked () ), - this, SLOT ( sinWaveClicked() ) ); - connect( m_triangleWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( triangleWaveClicked() ) ); - connect( m_sawWaveBtn, SIGNAL (clicked () ), - this, SLOT ( sawWaveClicked() ) ); - connect( m_sqrWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( sqrWaveClicked() ) ); - connect( m_whiteNoiseWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( noiseWaveClicked() ) ); - connect( m_usrWaveBtn, SIGNAL ( clicked () ), - this, SLOT ( usrWaveClicked() ) ); - - connect( m_smoothBtn, SIGNAL ( clicked () ), - this, SLOT ( smoothClicked() ) ); - - connect( m_interpolationToggle, SIGNAL( toggled( bool ) ), - this, SLOT ( interpolationToggled( bool ) ) ); - - connect( m_normalizeToggle, SIGNAL( toggled( bool ) ), - this, SLOT ( normalizeToggled( bool ) ) ); } -void bitInvaderView::modelChanged() +void sfxrInstrumentView::modelChanged() { - bitInvader * b = castModel(); + sfxrInstrument * s = castModel(); - m_graph->setModel( &b->m_graph ); - m_sampleLengthKnob->setModel( &b->m_sampleLength ); - m_interpolationToggle->setModel( &b->m_interpolation ); - m_normalizeToggle->setModel( &b->m_normalize ); + m_attKnob->setModel( &s->m_attModel ); + m_holdKnob->setModel( &s->m_holdModel ); + m_susKnob->setModel( &s->m_susModel ); + m_decKnob->setModel( &s->m_decModel ); + m_startFreqKnob->setModel( &s->m_startFreqModel ); + m_minFreqKnob->setModel( &s->m_minFreqModel ); + m_slideKnob->setModel( &s->m_slideModel ); + m_dSlideKnob->setModel( &s->m_dSlideModel ); + m_vibDepthKnob->setModel( &s->m_vibDepthModel ); + m_vibSpeedKnob->setModel( &s->m_vibSpeedModel ); + + m_changeAmtKnob->setModel( &s->m_changeAmtModel ); + m_changeSpeedKnob->setModel( &s->m_changeSpeedModel ); + + m_sqrDutyKnob->setModel( &s->m_sqrDutyModel ); + m_sqrSpeedKnob->setModel( &s->m_sqrSweepModel ); + + m_repeatSpeedKnob->setModel( &s->m_repeatSpeedModel ); + + m_phaserOffsetKnob->setModel( &s->m_phaserOffsetModel ); + m_phaserSweepKnob->setModel( &s->m_phaserSweepModel ); + + m_lpFilCutKnob->setModel( &s->m_lpFilCutModel ); + m_lpFilCutSweepKnob->setModel( &s->m_lpFilCutSweepModel ); + m_lpFilResoKnob->setModel( &s->m_lpFilResoModel ); + m_hpFilCutKnob->setModel( &s->m_hpFilCutModel ); + m_hpFilCutSweepKnob->setModel( &s->m_hpFilCutSweepModel ); + + m_waveBtnGroup->setModel( &s->m_waveFormModel ); } -void bitInvaderView::sinWaveClicked() +void sfxrInstrumentView::waveFormChanged() { - m_graph->model()->setWaveToSine(); - engine::getSong()->setModified(); -} - - - - -void bitInvaderView::triangleWaveClicked() -{ - m_graph->model()->setWaveToTriangle(); - engine::getSong()->setModified(); -} - - - - -void bitInvaderView::sawWaveClicked() -{ - m_graph->model()->setWaveToSaw(); - engine::getSong()->setModified(); -} - - - - -void bitInvaderView::sqrWaveClicked() -{ - m_graph->model()->setWaveToSquare(); - engine::getSong()->setModified(); -} - - - - -void bitInvaderView::noiseWaveClicked() -{ - m_graph->model()->setWaveToNoise(); - engine::getSong()->setModified(); -} - - - - -void bitInvaderView::usrWaveClicked() -{ - QString fileName = m_graph->model()->setWaveToUser(); - toolTip::add( m_usrWaveBtn, fileName ); - engine::getSong()->setModified(); + //TODO: do we even need this slot? /* m_graph->model()->setWaveToNoise(); engine::getSong()->setModified(); - // zero sample_shape - for (int i = 0; i < sample_length; i++) - { - sample_shape[i] = 0; - } - - // load user shape - sampleBuffer buffer; - QString af = buffer.openAudioFile(); - if ( af != "" ) - { - buffer.setAudioFile( af ); - - // copy buffer data - sample_length = min( sample_length, static_cast( - buffer.frames() ) ); - for ( int i = 0; i < sample_length; i++ ) - { - sample_shape[i] = (float)*buffer.data()[i]; - } - } - - sampleChanged(); */ } -void bitInvaderView::smoothClicked() +void sfxrInstrumentView::genPickup() { - m_graph->model()->smooth(); - engine::getSong()->setModified(); + sfxrInstrument * s = castModel(); + s->resetModels(); + s->m_startFreqModel.setValue( 0.4f+frnd(0.5f) ); + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( frnd(0.1f) ); + s->m_decModel.setValue( 0.1f+frnd(0.4f) ); + s->m_susModel.setValue( 0.3f+frnd(0.3f) ); + + if(rnd(1)) + { + s->m_changeAmtModel.setValue( 0.5f+frnd(0.2f) ); + s->m_changeSpeedModel.setValue( 0.2f+frnd(0.4f) ); + } } -void bitInvaderView::interpolationToggled( bool value ) +void sfxrInstrumentView::genLaser() { - m_graph->setGraphStyle( value ? graph::LinearStyle : graph::NearestStyle); - engine::getSong()->setModified(); + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( rnd(2) ); + if(s->m_waveFormModel.value()==2 && rnd(1)) + s->m_waveFormModel.setValue(rnd(1)); + + s->m_startFreqModel.setValue( 0.5f+frnd(0.5f) ); + s->m_minFreqModel.setValue( s->m_startFreqModel.value()-0.2f-frnd(0.6f) ); + + if(s->m_minFreqModel.value()<0.2f) + { + s->m_minFreqModel.setValue(0.2f); + } + + s->m_slideModel.setValue( -0.15f-frnd(0.2f) ); + + if(rnd(2)==0) + { + s->m_startFreqModel.setValue( 0.3f+frnd(0.6f) ); + s->m_minFreqModel.setValue( frnd(0.1f) ); + s->m_slideModel.setValue( -0.35f-frnd(0.3f) ); + } + + if(rnd(1)) + { + s->m_sqrDutyModel.setValue( frnd(0.5f) ); + s->m_sqrSweepModel.setValue( 0.2f ); + } + else + { + s->m_sqrDutyModel.setValue( 0.4f+frnd(0.5f) ); + s->m_sqrSweepModel.setValue( -frnd(0.7f) ); + } + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.2f) ); + s->m_decModel.setValue( frnd(0.4f) ); + + if(rnd(1)) + { + s->m_susModel.setValue( frnd(0.3f) ); + } + + if(rnd(2)==0) + { + s->m_phaserOffsetModel.setValue( frnd(0.2f) ); + s->m_phaserSweepModel.setValue( -frnd(0.2f) ); + } + + if(rnd(1)) + s->m_hpFilCutModel.setValue( frnd(0.3f) ); } -void bitInvaderView::normalizeToggled( bool value ) +void sfxrInstrumentView::genExplosion() { - engine::getSong()->setModified(); + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( 3 ); + + if(rnd(1)) + { + s->m_startFreqModel.setValue( 0.1f+frnd(0.4f) ); + s->m_slideModel.setValue( -0.1f+frnd(0.4f) ); + } + else + { + s->m_startFreqModel.setValue( 0.2f+frnd(0.7f) ); + s->m_slideModel.setValue( -0.2f-frnd(0.2f) ); + } + s->m_startFreqModel.setValue( s->m_startFreqModel.value()*s->m_startFreqModel.value() ); + + if(rnd(4)==0) + { + s->m_slideModel.setValue( 0.0f ); + } + + if(rnd(2)==0) + { + s->m_repeatSpeedModel.setValue( 0.3f+frnd(0.5f) ); + } + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.3f) ); + s->m_decModel.setValue( 0.5f ); + if(rnd(1)==0) + { + s->m_phaserOffsetModel.setValue( -0.3f+frnd(0.9f) ); + s->m_phaserSweepModel.setValue( -frnd(0.3f) ); + } + s->m_susModel.setValue( 0.2f+frnd(0.6f) ); + + if(rnd(1)) + { + s->m_vibDepthModel.setValue( frnd(0.7f) ); + s->m_vibSpeedModel.setValue( frnd(0.6f) ); + } + if(rnd(2)==0) + { + s->m_changeSpeedModel.setValue( 0.6f+frnd(0.3f) ); + s->m_changeAmtModel.setValue( 0.8f-frnd(1.6f) ); + } + +} + + + + +void sfxrInstrumentView::genPowerup() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + if(rnd(1)) + s->m_waveFormModel.setValue( 1 ); + else + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + if(rnd(1)) + { + s->m_startFreqModel.setValue( 0.2f+frnd(0.3f) ); + s->m_slideModel.setValue( 0.1f+frnd(0.4f) ); + s->m_repeatSpeedModel.setValue( 0.4f+frnd(0.4f) ); + } + else + { + s->m_startFreqModel.setValue( 0.2f+frnd(0.3f) ); + s->m_slideModel.setValue( 0.05f+frnd(0.2f) ); + if(rnd(1)) + { + s->m_vibDepthModel.setValue( frnd(0.7f) ); + s->m_vibSpeedModel.setValue( frnd(0.6f) ); + } + } + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( frnd(0.4f) ); + s->m_decModel.setValue( 0.1f+frnd(0.4f) ); +} + + + + +void sfxrInstrumentView::genHit() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( rnd(2) ); + if(s->m_waveFormModel.value()==2) + s->m_waveFormModel.setValue( 3 ); + if(s->m_waveFormModel.value()==0) + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + + s->m_startFreqModel.setValue( 0.2f+frnd(0.6f) ); + s->m_slideModel.setValue( -0.3f-frnd(0.4f) ); + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( frnd(0.1f) ); + s->m_decModel.setValue( 0.1f+frnd(0.2f) ); + if(rnd(1)) + { + s->m_hpFilCutModel.setValue( frnd(0.3f) ); + } +} + + + + +void sfxrInstrumentView::genJump() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( 0 ); + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + + s->m_startFreqModel.setValue( 0.3f+frnd(0.3f) ); + s->m_slideModel.setValue( 0.1f+frnd(0.2f) ); + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.3f) ); + s->m_decModel.setValue( 0.1f+frnd(0.2f) ); + + if(rnd(1)) + { + s->m_hpFilCutModel.setValue( frnd(0.3f) ); + } + + if(rnd(1)) + { + + s->m_lpFilCutModel.setValue( 1.0f-frnd(0.6f) ); + } +} + + + + +void sfxrInstrumentView::genBlip() +{ + sfxrInstrument * s = castModel(); + s->resetModels(); + + s->m_waveFormModel.setValue( rnd(1) ); + if( s->m_waveFormModel.value()==0 ) + { + s->m_sqrDutyModel.setValue( frnd(0.6f) ); + } + + s->m_startFreqModel.setValue( 0.2f+frnd(0.4f) ); + + s->m_attModel.setValue( 0.0f ); + s->m_holdModel.setValue( 0.1f+frnd(0.1f) ); + s->m_decModel.setValue( frnd(0.2f) ); + s->m_hpFilCutModel.setValue( 0.1f ); +} + + + + +void sfxrInstrumentView::randomize() +{ + sfxrInstrument * s = castModel(); + + s->m_startFreqModel.setValue( pow(frnd(2.0f)-1.0f, 2.0f) ); + if(rnd(1)) + { + s->m_startFreqModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f)+0.5f ); + } + s->m_minFreqModel.setValue( 0.0f ); + s->m_slideModel.setValue( pow(frnd(2.0f)-1.0f, 5.0f) ); + if( s->m_startFreqModel.value()>0.7f && s->m_slideModel.value()>0.2f ) + { + s->m_slideModel.setValue( -s->m_slideModel.value() ); + } + if( s->m_startFreqModel.value()<0.2f && s->m_slideModel.value()<-0.05f ) + { + s->m_slideModel.setValue( -s->m_slideModel.value() ); + } + s->m_dSlideModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + + s->m_sqrDutyModel.setValue( frnd(2.0f)-1.0f ); + s->m_sqrSweepModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + + s->m_vibDepthModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + s->m_vibSpeedModel.setValue( frnd(2.0f)-1.0f ); + //s->m_vibDelayModel.setValue( frnd(2.0f)-1.0f ); + + s->m_attModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + s->m_holdModel.setValue( pow(frnd(2.0f)-1.0f, 2.0f) ); + s->m_decModel.setValue( frnd(2.0f)-1.0f ); + s->m_susModel.setValue( pow(frnd(0.8f), 2.0f) ); + if(s->m_attModel.value()+s->m_holdModel.value()+s->m_decModel.value()<0.2f) + { + s->m_holdModel.setValue( s->m_holdModel.value()+0.2f+frnd(0.3f) ); + s->m_decModel.setValue( s->m_decModel.value()+0.2f+frnd(0.3f) ); + } + + s->m_lpFilResoModel.setValue( frnd(2.0f)-1.0f ); + s->m_lpFilCutModel.setValue( 1.0f-pow(frnd(1.0f), 3.0f) ); + s->m_lpFilCutSweepModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + if(s->m_lpFilCutModel.value()<0.1f && s->m_lpFilCutSweepModel.value()<-0.05f) + { + s->m_lpFilCutSweepModel.setValue( -s->m_lpFilCutSweepModel.value() ); + } + s->m_hpFilCutModel.setValue( pow(frnd(1.0f), 5.0f) ); + s->m_hpFilCutSweepModel.setValue( pow(frnd(2.0f)-1.0f, 5.0f) ); + + s->m_phaserOffsetModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + s->m_phaserSweepModel.setValue( pow(frnd(2.0f)-1.0f, 3.0f) ); + + s->m_repeatSpeedModel.setValue( frnd(2.0f)-1.0f ); + + s->m_changeSpeedModel.setValue( frnd(2.0f)-1.0f ); + s->m_changeAmtModel.setValue( frnd(2.0f)-1.0f ); + +} + + + + +void sfxrInstrumentView::mutate() +{ + sfxrInstrument * s = castModel(); + + if(rnd(1)) s->m_startFreqModel.setValue( s->m_startFreqModel.value()+frnd(0.1f)-0.05f ); + // if(rnd(1)) s->m_minFreqModel.setValue( s->m_minFreqModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_slideModel.setValue( s->m_slideModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_dSlideModel.setValue( s->m_dSlideModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_sqrDutyModel.setValue( s->m_sqrDutyModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_sqrSweepModel.setValue( s->m_sqrSweepModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_vibDepthModel.setValue( s->m_vibDepthModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_vibSpeedModel.setValue( s->m_vibSpeedModel.value()+frnd(0.1f)-0.05f ); + // if(rnd(1)) s->m_vibDelayModel.setValue( s->m_vibDelayModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_attModel.setValue( s->m_attModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_holdModel.setValue( s->m_holdModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_decModel.setValue( s->m_decModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_susModel.setValue( s->m_susModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_lpFilResoModel.setValue( s->m_lpFilResoModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_lpFilCutModel.setValue( s->m_lpFilCutModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_lpFilCutSweepModel.setValue( s->m_lpFilCutSweepModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_hpFilCutModel.setValue( s->m_hpFilCutModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_hpFilCutSweepModel.setValue( s->m_hpFilCutSweepModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_phaserOffsetModel.setValue( s->m_phaserOffsetModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_phaserSweepModel.setValue( s->m_phaserSweepModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_repeatSpeedModel.setValue( s->m_repeatSpeedModel.value()+frnd(0.1f)-0.05f ); + + if(rnd(1)) s->m_changeSpeedModel.setValue( s->m_changeSpeedModel.value()+frnd(0.1f)-0.05f ); + if(rnd(1)) s->m_changeAmtModel.setValue( s->m_changeAmtModel.value()+frnd(0.1f)-0.05f ); + } @@ -580,7 +925,7 @@ extern "C" // necessary for getting instance out of shared lib Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) { - return( new bitInvader( static_cast( _data ) ) ); + return( new sfxrInstrument( static_cast( _data ) ) ); } @@ -588,4 +933,4 @@ Plugin * PLUGIN_EXPORT lmms_plugin_main( Model *, void * _data ) -#include "moc_bit_invader.cxx" +#include "moc_sfxr.cxx" diff --git a/plugins/sfxr/sfxr.h b/plugins/sfxr/sfxr.h index 3b2320e80..e363dd343 100644 --- a/plugins/sfxr/sfxr.h +++ b/plugins/sfxr/sfxr.h @@ -1,5 +1,6 @@ /* * sfxr.h - declaration of classes of the LMMS sfxr plugin + * The original readme file of sfxr can be found in readme.txt in this directory. * * Copyright (c) 2014 Wong Cho Ching * @@ -29,19 +30,44 @@ #include "Instrument.h" #include "InstrumentView.h" #include "knob.h" +#include "graph.h" #include "pixmap_button.h" #include "led_checkbox.h" -class bitInvaderView; -class bSynth +enum SfxrWaves +{ + SQR_WAVE, SAW_WAVE, SINE_WAVE, NOISE_WAVE, WAVES_NUM +}; + +const int WAVEFORM_BASE_X = 20; +const int WAVEFORM_BASE_Y = 14; +const int WAVEFORM_BUTTON_WIDTH = 16; + +const int GENERATOR_BASE_X = 110; +const int GENERATOR_BASE_Y = 24; +const int GENERATOR_BUTTON_WIDTH = 16; + +const int RAND_BUTTON_X = 160; +const int RAND_BUTTON_Y = 4; + +const int MUTA_BUTTON_X = 205; +const int MUTA_BUTTON_Y = 4; + +const int KNOBS_BASE_X = 20; +const int KNOBS_BASE_Y = 50; +const int KNOB_BLOCK_SIZE_X = 40; +const int KNOB_BLOCK_SIZE_Y = 40; + + +class SfxrSynth { public: - bSynth( float * sample, int length, notePlayHandle * _nph, - bool _interpolation, float factor, + SfxrSynth( float * sample, int length, notePlayHandle * _nph, + bool _interpolation, float factor, const sample_rate_t _sample_rate ); - virtual ~bSynth(); - + virtual ~SfxrSynth(); + sample_t nextStringSample(); @@ -54,15 +80,39 @@ private: const sample_rate_t sample_rate; bool interpolation; - -} ; -class bitInvader : public Instrument +}; + +/** + * @brief A class that simplify the constructor of FloatModel, with value [0,1] + */ +class SfxrZeroToOneFloatModel : public FloatModel +{ +public: + SfxrZeroToOneFloatModel(float val, Model * parent): + FloatModel( val, 0.0, 1.0, 0.001, parent) + { + } +}; + +/** + * @brief A class that simplify the constructor of FloatModel, with value [-1,1] + */ +class SfxrNegPosOneFloatModel : public FloatModel +{ +public: + SfxrNegPosOneFloatModel(float val, Model * parent): + FloatModel( val, -1.0, 1.0, 0.001, parent) + { + } +}; + +class sfxrInstrument : public Instrument { Q_OBJECT public: - bitInvader(InstrumentTrack * _instrument_track ); - virtual ~bitInvader(); + sfxrInstrument(InstrumentTrack * _instrument_track ); + virtual ~sfxrInstrument(); virtual void playNote( notePlayHandle * _n, sampleFrame * _working_buffer ); @@ -75,77 +125,127 @@ public: virtual QString nodeName() const; - virtual f_cnt_t desiredReleaseFrames() const - { - return( 64 ); - } + virtual f_cnt_t desiredReleaseFrames() const; virtual PluginView * instantiateView( QWidget * _parent ); -protected slots: - void lengthChanged(); - void samplesChanged( int, int ); + void resetModels(); - void normalize(); +protected slots: + void samplesChanged( int, int ); private: - FloatModel m_sampleLength; - graphModel m_graph; - - BoolModel m_interpolation; - BoolModel m_normalize; - - float m_normalizeFactor; + SfxrZeroToOneFloatModel m_attModel; + SfxrZeroToOneFloatModel m_holdModel; + SfxrZeroToOneFloatModel m_susModel; + SfxrZeroToOneFloatModel m_decModel; - friend class bitInvaderView; -} ; + SfxrZeroToOneFloatModel m_startFreqModel; + SfxrZeroToOneFloatModel m_minFreqModel; + SfxrNegPosOneFloatModel m_slideModel; + SfxrNegPosOneFloatModel m_dSlideModel; + SfxrZeroToOneFloatModel m_vibDepthModel; + SfxrZeroToOneFloatModel m_vibSpeedModel; + + SfxrNegPosOneFloatModel m_changeAmtModel; + SfxrZeroToOneFloatModel m_changeSpeedModel; + + SfxrZeroToOneFloatModel m_sqrDutyModel; + SfxrNegPosOneFloatModel m_sqrSweepModel; + + SfxrZeroToOneFloatModel m_repeatSpeedModel; + + SfxrNegPosOneFloatModel m_phaserOffsetModel; + SfxrNegPosOneFloatModel m_phaserSweepModel; + + SfxrZeroToOneFloatModel m_lpFilCutModel; + SfxrNegPosOneFloatModel m_lpFilCutSweepModel; + SfxrZeroToOneFloatModel m_lpFilResoModel; + SfxrZeroToOneFloatModel m_hpFilCutModel; + SfxrNegPosOneFloatModel m_hpFilCutSweepModel; + + IntModel m_waveFormModel; + + friend class sfxrInstrumentView; +}; -class bitInvaderView : public InstrumentView +class sfxrInstrumentView : public InstrumentView { Q_OBJECT public: - bitInvaderView( Instrument * _instrument, + sfxrInstrumentView( Instrument * _instrument, QWidget * _parent ); - virtual ~bitInvaderView() {}; + virtual ~sfxrInstrumentView() {}; protected slots: - //void sampleSizeChanged( float _new_sample_length ); - - void interpolationToggled( bool value ); - void normalizeToggled( bool value ); - - void sinWaveClicked(); - void triangleWaveClicked(); - void sqrWaveClicked(); - void sawWaveClicked(); - void noiseWaveClicked(); - void usrWaveClicked(); - - void smoothClicked( void ); + void waveFormChanged(); + void genPickup(); + void genLaser(); + void genExplosion(); + void genPowerup(); + void genHit(); + void genJump(); + void genBlip(); + void randomize(); + void mutate(); private: virtual void modelChanged(); - knob * m_sampleLengthKnob; - pixmapButton * m_sinWaveBtn; - pixmapButton * m_triangleWaveBtn; - pixmapButton * m_sqrWaveBtn; + knob * m_attKnob; //Attack Time + knob * m_holdKnob; //Sustain Time + knob * m_susKnob; //Sustain Punch + knob * m_decKnob; //Decay Time + + knob * m_startFreqKnob; //Start Frequency + knob * m_minFreqKnob; //Min Frequency + knob * m_slideKnob; //Slide + knob * m_dSlideKnob; //Delta Slide + knob * m_vibDepthKnob; //Vibrato Depth + knob * m_vibSpeedKnob; //Vibrato Speed + + knob * m_changeAmtKnob; //Change Amount + knob * m_changeSpeedKnob; //Change Speed + + knob * m_sqrDutyKnob; //Squre Duty + knob * m_sqrSpeedKnob; //Squre Sweep + + knob * m_repeatSpeedKnob; //Repeat Speed + + knob * m_phaserOffsetKnob; //Phaser Offset + knob * m_phaserSweepKnob; //Phaser Sweep + + knob * m_lpFilCutKnob; //LP Filter Cutoff + knob * m_lpFilCutSweepKnob; //LP Filter Cutoff Sweep + knob * m_lpFilResoKnob; //LP Filter Resonance + knob * m_hpFilCutKnob; //HP Filter Cutoff + knob * m_hpFilCutSweepKnob; //HP Filter Cutoff Sweep + + automatableButtonGroup * m_waveBtnGroup; + pixmapButton * m_sqrWaveBtn; //NOTE: This button has Squre Duty + //and Squre Speed configurable pixmapButton * m_sawWaveBtn; - pixmapButton * m_whiteNoiseWaveBtn; - pixmapButton * m_smoothBtn; - pixmapButton * m_usrWaveBtn; + pixmapButton * m_sinWaveBtn; + pixmapButton * m_noiseWaveBtn; + + + pixmapButton * m_pickupBtn; + pixmapButton * m_laserBtn; + pixmapButton * m_explosionBtn; + pixmapButton * m_powerupBtn; + pixmapButton * m_hitBtn; + pixmapButton * m_jumpBtn; + pixmapButton * m_blipBtn; + + pixmapButton * m_randomizeBtn; + pixmapButton * m_mutateBtn; static QPixmap * s_artwork; - - graph * m_graph; - ledCheckBox * m_interpolationToggle; - ledCheckBox * m_normalizeToggle; - -} ; +};