1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291 |
- /*
- * Watsyn.cpp - a 4-oscillator modulating wavetable synth
- *
- * Copyright (c) 2014 Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>
- *
- * This file is part of LMMS - https://lmms.io
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * 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 <QDomElement>
- #include "Watsyn.h"
- #include "base64.h"
- #include "AudioEngine.h"
- #include "Engine.h"
- #include "InstrumentTrack.h"
- #include "ToolTip.h"
- #include "Song.h"
- #include "lmms_math.h"
- #include "interpolation.h"
- #include "embed.h"
- #include "plugin_export.h"
- extern "C"
- {
- Plugin::Descriptor PLUGIN_EXPORT watsyn_plugin_descriptor =
- {
- STRINGIFY( PLUGIN_NAME ),
- "Watsyn",
- QT_TRANSLATE_NOOP( "PluginBrowser",
- "4-oscillator modulatable wavetable synth" ),
- "Vesa Kivimäki <contact/dot/diizy/at/nbl/dot/fi>",
- 0x0100,
- Plugin::Instrument,
- new PluginPixmapLoader( "logo" ),
- nullptr,
- nullptr,
- } ;
- }
- WatsynObject::WatsynObject( float * _A1wave, float * _A2wave,
- float * _B1wave, float * _B2wave,
- int _amod, int _bmod, const sample_rate_t _samplerate, NotePlayHandle * _nph, fpp_t _frames,
- WatsynInstrument * _w ) :
- m_amod( _amod ),
- m_bmod( _bmod ),
- m_samplerate( _samplerate ),
- m_nph( _nph ),
- m_fpp( _frames ),
- m_parent( _w )
- {
- m_abuf = new sampleFrame[_frames];
- m_bbuf = new sampleFrame[_frames];
- m_lphase[A1_OSC] = 0.0f;
- m_lphase[A2_OSC] = 0.0f;
- m_lphase[B1_OSC] = 0.0f;
- m_lphase[B2_OSC] = 0.0f;
- m_rphase[A1_OSC] = 0.0f;
- m_rphase[A2_OSC] = 0.0f;
- m_rphase[B1_OSC] = 0.0f;
- m_rphase[B2_OSC] = 0.0f;
- // copy wavegraphs to the synth object to prevent race conditions
- memcpy( &m_A1wave, _A1wave, sizeof( m_A1wave ) );
- memcpy( &m_A2wave, _A2wave, sizeof( m_A2wave ) );
- memcpy( &m_B1wave, _B1wave, sizeof( m_B1wave ) );
- memcpy( &m_B2wave, _B2wave, sizeof( m_B2wave ) );
- }
- WatsynObject::~WatsynObject()
- {
- delete[] m_abuf;
- delete[] m_bbuf;
- }
- void WatsynObject::renderOutput( fpp_t _frames )
- {
- if( m_abuf == nullptr )
- m_abuf = new sampleFrame[m_fpp];
- if( m_bbuf == nullptr )
- m_bbuf = new sampleFrame[m_fpp];
- for( fpp_t frame = 0; frame < _frames; frame++ )
- {
- // put phases of 1-series oscs into variables because phase modulation might happen
- float A1_lphase = m_lphase[A1_OSC];
- float A1_rphase = m_rphase[A1_OSC];
- float B1_lphase = m_lphase[B1_OSC];
- float B1_rphase = m_rphase[B1_OSC];
- ///////////// A-series /////////////////
- // A2
- sample_t A2_L = linearInterpolate( m_A2wave[ static_cast<int>( m_lphase[A2_OSC] ) ],
- m_A2wave[ static_cast<int>( m_lphase[A2_OSC] + 1 ) % WAVELEN ],
- fraction( m_lphase[A2_OSC] ) ) * m_parent->m_lvol[A2_OSC];
- sample_t A2_R = linearInterpolate( m_A2wave[ static_cast<int>( m_rphase[A2_OSC] ) ],
- m_A2wave[ static_cast<int>( m_rphase[A2_OSC] + 1 ) % WAVELEN ],
- fraction( m_rphase[A2_OSC] ) ) * m_parent->m_rvol[A2_OSC];
- // if phase mod, add to phases
- if( m_amod == MOD_PM )
- {
- A1_lphase = fmodf( A1_lphase + A2_L * PMOD_AMT, WAVELEN );
- if( A1_lphase < 0 ) A1_lphase += WAVELEN;
- A1_rphase = fmodf( A1_rphase + A2_R * PMOD_AMT, WAVELEN );
- if( A1_rphase < 0 ) A1_rphase += WAVELEN;
- }
- // A1
- sample_t A1_L = linearInterpolate( m_A1wave[ static_cast<int>( A1_lphase ) ],
- m_A1wave[ static_cast<int>( A1_lphase + 1 ) % WAVELEN ],
- fraction( A1_lphase ) ) * m_parent->m_lvol[A1_OSC];
- sample_t A1_R = linearInterpolate( m_A1wave[ static_cast<int>( A1_rphase ) ],
- m_A1wave[ static_cast<int>( A1_rphase + 1 ) % WAVELEN ],
- fraction( A1_rphase ) ) * m_parent->m_rvol[A1_OSC];
- ///////////// B-series /////////////////
- // B2
- sample_t B2_L = linearInterpolate( m_B2wave[ static_cast<int>( m_lphase[B2_OSC] ) ],
- m_B2wave[ static_cast<int>( m_lphase[B2_OSC] + 1 ) % WAVELEN ],
- fraction( m_lphase[B2_OSC] ) ) * m_parent->m_lvol[B2_OSC];
- sample_t B2_R = linearInterpolate( m_B2wave[ static_cast<int>( m_rphase[B2_OSC] ) ],
- m_B2wave[ static_cast<int>( m_rphase[B2_OSC] + 1 ) % WAVELEN ],
- fraction( m_rphase[B2_OSC] ) ) * m_parent->m_rvol[B2_OSC];
- // if crosstalk active, add a1
- const float xt = m_parent->m_xtalk.value();
- if( xt > 0.0 )
- {
- B2_L += ( A1_L * xt ) * 0.01f;
- B2_R += ( A1_R * xt ) * 0.01f;
- }
- // if phase mod, add to phases
- if( m_bmod == MOD_PM )
- {
- B1_lphase = fmodf( B1_lphase + B2_L * PMOD_AMT, WAVELEN );
- if( B1_lphase < 0 ) B1_lphase += WAVELEN;
- B1_rphase = fmodf( B1_rphase + B2_R * PMOD_AMT, WAVELEN );
- if( B1_rphase < 0 ) B1_rphase += WAVELEN;
- }
- // B1
- sample_t B1_L = linearInterpolate( m_B1wave[ static_cast<int>( B1_lphase ) % WAVELEN ],
- m_B1wave[ static_cast<int>( B1_lphase + 1 ) % WAVELEN ],
- fraction( B1_lphase ) ) * m_parent->m_lvol[B1_OSC];
- sample_t B1_R = linearInterpolate( m_B1wave[ static_cast<int>( B1_rphase ) % WAVELEN ],
- m_B1wave[ static_cast<int>( B1_rphase + 1 ) % WAVELEN ],
- fraction( B1_rphase ) ) * m_parent->m_rvol[B1_OSC];
- // A-series modulation)
- switch( m_amod )
- {
- case MOD_MIX:
- A1_L = ( A1_L + A2_L ) / 2.0;
- A1_R = ( A1_R + A2_R ) / 2.0;
- break;
- case MOD_AM:
- A1_L *= qMax( 0.0f, A2_L + 1.0f );
- A1_R *= qMax( 0.0f, A2_R + 1.0f );
- break;
- case MOD_RM:
- A1_L *= A2_L;
- A1_R *= A2_R;
- break;
- }
- m_abuf[frame][0] = A1_L;
- m_abuf[frame][1] = A1_R;
- // B-series modulation (other than phase mod)
- switch( m_bmod )
- {
- case MOD_MIX:
- B1_L = ( B1_L + B2_L ) / 2.0;
- B1_R = ( B1_R + B2_R ) / 2.0;
- break;
- case MOD_AM:
- B1_L *= qMax( 0.0f, B2_L + 1.0f );
- B1_R *= qMax( 0.0f, B2_R + 1.0f );
- break;
- case MOD_RM:
- B1_L *= B2_L;
- B1_R *= B2_R;
- break;
- }
- m_bbuf[frame][0] = B1_L;
- m_bbuf[frame][1] = B1_R;
- // update phases
- for( int i = 0; i < NUM_OSCS; i++ )
- {
- m_lphase[i] += ( static_cast<float>( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_lfreq[i] ) ) );
- m_lphase[i] = fmodf( m_lphase[i], WAVELEN );
- m_rphase[i] += ( static_cast<float>( WAVELEN ) / ( m_samplerate / ( m_nph->frequency() * m_parent->m_rfreq[i] ) ) );
- m_rphase[i] = fmodf( m_rphase[i], WAVELEN );
- }
- }
- }
- WatsynInstrument::WatsynInstrument( InstrumentTrack * _instrument_track ) :
- Instrument( _instrument_track, &watsyn_plugin_descriptor ),
- a1_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A1" ) ),
- a2_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume A2" ) ),
- b1_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume B1" ) ),
- b2_vol( 100.0f, 0.0f, 200.0f, 0.1f, this, tr( "Volume B2" ) ),
- a1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning A1" ) ),
- a2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning A2" ) ),
- b1_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B1" ) ),
- b2_pan( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "Panning B2" ) ),
- a1_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier A1" ) ),
- a2_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier A2" ) ),
- b1_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier B1" ) ),
- b2_mult( 8.0f, 1.0, 24.0, 1.0, this, tr( "Freq. multiplier B2" ) ),
- a1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A1" ) ),
- a2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune A2" ) ),
- b1_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune B1" ) ),
- b2_ltune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Left detune B2" ) ),
- a1_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune A1" ) ),
- a2_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune A2" ) ),
- b1_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B1" ) ),
- b2_rtune( 0.0f, -600.0f, 600.0f, 1.0f, this, tr( "Right detune B2" ) ),
- a1_graph( -1.0f, 1.0f, GRAPHLEN, this ),
- a2_graph( -1.0f, 1.0f, GRAPHLEN, this ),
- b1_graph( -1.0f, 1.0f, GRAPHLEN, this ),
- b2_graph( -1.0f, 1.0f, GRAPHLEN, this ),
- m_abmix( 0.0f, -100.0f, 100.0f, 0.1f, this, tr( "A-B Mix" ) ),
- m_envAmt( 0.0f, -200.0f, 200.0f, 1.0f, this, tr( "A-B Mix envelope amount" ) ),
- m_envAtt( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope attack" ) ),
- m_envHold( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope hold" ) ),
- m_envDec( 0.0f, 0.0f, 2000.0f, 1.0f, 2000.0f, this, tr( "A-B Mix envelope decay" ) ),
- m_xtalk( 0.0f, 0.0f, 100.0f, 0.1f, this, tr( "A1-B2 Crosstalk" ) ),
- m_amod( 0, 0, 3, this, tr( "A2-A1 modulation" ) ),
- m_bmod( 0, 0, 3, this, tr( "B2-B1 modulation" ) ),
- m_selectedGraph( 0, 0, 3, this, tr( "Selected graph" ) )
- {
- connect( &a1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &a2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &b1_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &b2_vol, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &a1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &a2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &b1_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &b2_pan, SIGNAL( dataChanged() ), this, SLOT( updateVolumes() ) );
- connect( &a1_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreqA1() ) );
- connect( &a2_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreqA2() ) );
- connect( &b1_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreqB1() ) );
- connect( &b2_mult, SIGNAL( dataChanged() ), this, SLOT( updateFreqB2() ) );
- connect( &a1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreqA1() ) );
- connect( &a2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreqA2() ) );
- connect( &b1_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreqB1() ) );
- connect( &b2_ltune, SIGNAL( dataChanged() ), this, SLOT( updateFreqB2() ) );
- connect( &a1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreqA1() ) );
- connect( &a2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreqA2() ) );
- connect( &b1_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreqB1() ) );
- connect( &b2_rtune, SIGNAL( dataChanged() ), this, SLOT( updateFreqB2() ) );
-
- connect( &a1_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaveA1() ) );
- connect( &a2_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaveA2() ) );
- connect( &b1_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaveB1() ) );
- connect( &b2_graph, SIGNAL( samplesChanged( int, int ) ), this, SLOT( updateWaveB2() ) );
- a1_graph.setWaveToSine();
- a2_graph.setWaveToSine();
- b1_graph.setWaveToSine();
- b2_graph.setWaveToSine();
- updateVolumes();
- updateFreqA1();
- updateFreqA2();
- updateFreqB1();
- updateFreqB2();
- updateWaveA1();
- updateWaveA2();
- updateWaveB1();
- updateWaveB2();
- }
- WatsynInstrument::~WatsynInstrument()
- {
- }
- void WatsynInstrument::playNote( NotePlayHandle * _n,
- sampleFrame * _working_buffer )
- {
- if ( _n->totalFramesPlayed() == 0 || _n->m_pluginData == nullptr )
- {
- WatsynObject * w = new WatsynObject(
- &A1_wave[0],
- &A2_wave[0],
- &B1_wave[0],
- &B2_wave[0],
- m_amod.value(), m_bmod.value(),
- Engine::audioEngine()->processingSampleRate(), _n,
- Engine::audioEngine()->framesPerPeriod(), this );
- _n->m_pluginData = w;
- }
- const fpp_t frames = _n->framesLeftForCurrentPeriod();
- const f_cnt_t offset = _n->noteOffset();
- sampleFrame * buffer = _working_buffer + offset;
- WatsynObject * w = static_cast<WatsynObject *>( _n->m_pluginData );
- sampleFrame * abuf = w->abuf();
- sampleFrame * bbuf = w->bbuf();
- w-> renderOutput( frames );
- // envelope parameters
- const float envAmt = m_envAmt.value();
- const float envAtt = ( m_envAtt.value() * w->samplerate() ) / 1000.0f;
- const float envHold = ( m_envHold.value() * w->samplerate() ) / 1000.0f;
- const float envDec = ( m_envDec.value() * w->samplerate() ) / 1000.0f;
- const float envLen = envAtt + envDec + envHold;
- const float tfp_ = static_cast<float>( _n->totalFramesPlayed() );
- // if sample-exact is enabled, use sample-exact calculations...
- // disabled pending proper implementation of sample-exactness
- /* if( engine::audioEngine()->currentQualitySettings().sampleExactControllers )
- {
- for( fpp_t f=0; f < frames; f++ )
- {
- const float tfp = tfp_ + f;
- // handle mixing envelope
- float mixvalue = m_abmix.value( f );
- if( envAmt != 0.0f && tfp < envLen )
- {
- if( tfp < envAtt )
- {
- mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f );
- }
- else if ( tfp >= envAtt && tfp < envAtt + envHold )
- {
- mixvalue = qBound( -100.0f, mixvalue + envAmt, 100.0f );
- }
- else
- {
- mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - ( envAtt + envHold ) ) / envDec * envAmt ), 100.0f );
- }
- }
- // get knob values in sample-exact way
- const float bmix = ( ( mixvalue + 100.0 ) / 200.0 );
- const float amix = 1.0 - bmix;
- // mix a/b streams according to mixing knob
- _working_buffer[f][0] = ( abuf[f][0] * amix ) +
- ( bbuf[f][0] * bmix );
- _working_buffer[f][1] = ( abuf[f][1] * amix ) +
- ( bbuf[f][1] * bmix );
- }
- }
- else*/
-
- // if sample-exact is not enabled, use simpler calculations:
- // if mix envelope is active, and we haven't gone past the envelope end, use envelope-aware calculation...
- if( envAmt != 0.0f && tfp_ < envLen )
- {
- const float mixvalue_ = m_abmix.value();
- for( fpp_t f=0; f < frames; f++ )
- {
- float mixvalue = mixvalue_;
- const float tfp = tfp_ + f;
- // handle mixing envelope
- if( tfp < envAtt )
- {
- mixvalue = qBound( -100.0f, mixvalue + ( tfp / envAtt * envAmt ), 100.0f );
- }
- else if ( tfp >= envAtt && tfp < envAtt + envHold )
- {
- mixvalue = qBound( -100.0f, mixvalue + envAmt, 100.0f );
- }
- else
- {
- mixvalue = qBound( -100.0f, mixvalue + envAmt - ( ( tfp - ( envAtt + envHold ) ) / envDec * envAmt ), 100.0f );
- }
- // get knob values
- const float bmix = ( ( mixvalue + 100.0 ) / 200.0 );
- const float amix = 1.0 - bmix;
- // mix a/b streams according to mixing knob
- buffer[f][0] = ( abuf[f][0] * amix ) +
- ( bbuf[f][0] * bmix );
- buffer[f][1] = ( abuf[f][1] * amix ) +
- ( bbuf[f][1] * bmix );
- }
- }
- // ... mix envelope is inactive or we've past the end of envelope, so use a faster calculation to save cpu
- else
- {
- // get knob values
- const float bmix = ( ( m_abmix.value() + 100.0 ) / 200.0 );
- const float amix = 1.0 - bmix;
- for( fpp_t f=0; f < frames; f++ )
- {
- // mix a/b streams according to mixing knob
- buffer[f][0] = ( abuf[f][0] * amix ) +
- ( bbuf[f][0] * bmix );
- buffer[f][1] = ( abuf[f][1] * amix ) +
- ( bbuf[f][1] * bmix );
- }
- }
- applyRelease( _working_buffer, _n );
- instrumentTrack()->processAudioBuffer( _working_buffer, frames + offset, _n );
- }
- void WatsynInstrument::deleteNotePluginData( NotePlayHandle * _n )
- {
- delete static_cast<WatsynObject *>( _n->m_pluginData );
- }
- void WatsynInstrument::saveSettings( QDomDocument & _doc,
- QDomElement & _this )
- {
- a1_vol.saveSettings( _doc, _this, "a1_vol" );
- a2_vol.saveSettings( _doc, _this, "a2_vol" );
- b1_vol.saveSettings( _doc, _this, "b1_vol" );
- b2_vol.saveSettings( _doc, _this, "b2_vol" );
- a1_pan.saveSettings( _doc, _this, "a1_pan" );
- a2_pan.saveSettings( _doc, _this, "a2_pan" );
- b1_pan.saveSettings( _doc, _this, "b1_pan" );
- b2_pan.saveSettings( _doc, _this, "b2_pan" );
- a1_mult.saveSettings( _doc, _this, "a1_mult" );
- a2_mult.saveSettings( _doc, _this, "a2_mult" );
- b1_mult.saveSettings( _doc, _this, "b1_mult" );
- b2_mult.saveSettings( _doc, _this, "b2_mult" );
- a1_ltune.saveSettings( _doc, _this, "a1_ltune" );
- a2_ltune.saveSettings( _doc, _this, "a2_ltune" );
- b1_ltune.saveSettings( _doc, _this, "b1_ltune" );
- b2_ltune.saveSettings( _doc, _this, "b2_ltune" );
- a1_rtune.saveSettings( _doc, _this, "a1_rtune" );
- a2_rtune.saveSettings( _doc, _this, "a2_rtune" );
- b1_rtune.saveSettings( _doc, _this, "b1_rtune" );
- b2_rtune.saveSettings( _doc, _this, "b2_rtune" );
- // save graphs
- QString sampleString;
- base64::encode( (const char *)a1_graph.samples(), a1_graph.length() * sizeof(float), sampleString );
- _this.setAttribute( "a1_wave", sampleString );
- base64::encode( (const char *)a2_graph.samples(), a2_graph.length() * sizeof(float), sampleString );
- _this.setAttribute( "a2_wave", sampleString );
- base64::encode( (const char *)b1_graph.samples(), b1_graph.length() * sizeof(float), sampleString );
- _this.setAttribute( "b1_wave", sampleString );
- base64::encode( (const char *)b2_graph.samples(), b2_graph.length() * sizeof(float), sampleString );
- _this.setAttribute( "b2_wave", sampleString );
- m_abmix.saveSettings( _doc, _this, "abmix" );
- m_envAmt.saveSettings( _doc, _this, "envAmt" );
- m_envAtt.saveSettings( _doc, _this, "envAtt" );
- m_envHold.saveSettings( _doc, _this, "envHold" );
- m_envDec.saveSettings( _doc, _this, "envDec" );
- m_xtalk.saveSettings( _doc, _this, "xtalk" );
- m_amod.saveSettings( _doc, _this, "amod" );
- m_bmod.saveSettings( _doc, _this, "bmod" );
- /* m_selectedGraph.saveSettings( _doc, _this, "selgraph" );*/
- }
- void WatsynInstrument::loadSettings( const QDomElement & _this )
- {
- a1_vol.loadSettings( _this, "a1_vol" );
- a2_vol.loadSettings( _this, "a2_vol" );
- b1_vol.loadSettings( _this, "b1_vol" );
- b2_vol.loadSettings( _this, "b2_vol" );
- a1_pan.loadSettings( _this, "a1_pan" );
- a2_pan.loadSettings( _this, "a2_pan" );
- b1_pan.loadSettings( _this, "b1_pan" );
- b2_pan.loadSettings( _this, "b2_pan" );
- a1_mult.loadSettings( _this, "a1_mult" );
- a2_mult.loadSettings( _this, "a2_mult" );
- b1_mult.loadSettings( _this, "b1_mult" );
- b2_mult.loadSettings( _this, "b2_mult" );
- a1_ltune.loadSettings( _this, "a1_ltune" );
- a2_ltune.loadSettings( _this, "a2_ltune" );
- b1_ltune.loadSettings( _this, "b1_ltune" );
- b2_ltune.loadSettings( _this, "b2_ltune" );
- a1_rtune.loadSettings( _this, "a1_rtune" );
- a2_rtune.loadSettings( _this, "a2_rtune" );
- b1_rtune.loadSettings( _this, "b1_rtune" );
- b2_rtune.loadSettings( _this, "b2_rtune" );
- // load graphs
- int size = 0;
- char * dst = 0;
- base64::decode( _this.attribute( "a1_wave"), &dst, &size );
- a1_graph.setSamples( (float*) dst );
- base64::decode( _this.attribute( "a2_wave"), &dst, &size );
- a2_graph.setSamples( (float*) dst );
- base64::decode( _this.attribute( "b1_wave"), &dst, &size );
- b1_graph.setSamples( (float*) dst );
- base64::decode( _this.attribute( "b2_wave"), &dst, &size );
- b2_graph.setSamples( (float*) dst );
- delete[] dst;
- m_abmix.loadSettings( _this, "abmix" );
- m_envAmt.loadSettings( _this, "envAmt" );
- m_envAtt.loadSettings( _this, "envAtt" );
- m_envHold.loadSettings( _this, "envHold" );
- m_envDec.loadSettings( _this, "envDec" );
- m_xtalk.loadSettings( _this, "xtalk" );
- m_amod.loadSettings( _this, "amod" );
- m_bmod.loadSettings( _this, "bmod" );
- /* m_selectedGraph.loadSettings( _this, "selgraph" );*/
- }
- QString WatsynInstrument::nodeName() const
- {
- return( watsyn_plugin_descriptor.name );
- }
- PluginView * WatsynInstrument::instantiateView( QWidget * _parent )
- {
- return( new WatsynView( this, _parent ) );
- }
- void WatsynInstrument::updateVolumes()
- {
- m_lvol[A1_OSC] = leftCh( a1_vol.value(), a1_pan.value() );
- m_rvol[A1_OSC] = rightCh( a1_vol.value(), a1_pan.value() );
- m_lvol[A2_OSC] = leftCh( a2_vol.value(), a2_pan.value() );
- m_rvol[A2_OSC] = rightCh( a2_vol.value(), a2_pan.value() );
- m_lvol[B1_OSC] = leftCh( b1_vol.value(), b1_pan.value() );
- m_rvol[B1_OSC] = rightCh( b1_vol.value(), b1_pan.value() );
- m_lvol[B2_OSC] = leftCh( b2_vol.value(), b2_pan.value() );
- m_rvol[B2_OSC] = rightCh( b2_vol.value(), b2_pan.value() );
- }
- void WatsynInstrument::updateFreqA1()
- {
- // calculate frequencies
- m_lfreq[A1_OSC] = ( a1_mult.value() / 8 ) * powf( 2, a1_ltune.value() / 1200 );
- m_rfreq[A1_OSC] = ( a1_mult.value() / 8 ) * powf( 2, a1_rtune.value() / 1200 );
- }
- void WatsynInstrument::updateFreqA2()
- {
- // calculate frequencies
- m_lfreq[A2_OSC] = ( a2_mult.value() / 8 ) * powf( 2, a2_ltune.value() / 1200 );
- m_rfreq[A2_OSC] = ( a2_mult.value() / 8 ) * powf( 2, a2_rtune.value() / 1200 );
- }
- void WatsynInstrument::updateFreqB1()
- {
- // calculate frequencies
- m_lfreq[B1_OSC] = ( b1_mult.value() / 8 ) * powf( 2, b1_ltune.value() / 1200 );
- m_rfreq[B1_OSC] = ( b1_mult.value() / 8 ) * powf( 2, b1_rtune.value() / 1200 );
- }
- void WatsynInstrument::updateFreqB2()
- {
- // calculate frequencies
- m_lfreq[B2_OSC] = ( b2_mult.value() / 8 ) * powf( 2, b2_ltune.value() / 1200 );
- m_rfreq[B2_OSC] = ( b2_mult.value() / 8 ) * powf( 2, b2_rtune.value() / 1200 );
- }
- void WatsynInstrument::updateWaveA1()
- {
- // do sinc+oversampling on the wavetables to improve quality
- srccpy( &A1_wave[0], const_cast<float*>( a1_graph.samples() ) );
- }
- void WatsynInstrument::updateWaveA2()
- {
- // do sinc+oversampling on the wavetables to improve quality
- srccpy( &A2_wave[0], const_cast<float*>( a2_graph.samples() ) );
- }
- void WatsynInstrument::updateWaveB1()
- {
- // do sinc+oversampling on the wavetables to improve quality
- srccpy( &B1_wave[0], const_cast<float*>( b1_graph.samples() ) );
- }
- void WatsynInstrument::updateWaveB2()
- {
- // do sinc+oversampling on the wavetables to improve quality
- srccpy( &B2_wave[0], const_cast<float*>( b2_graph.samples() ) );
- }
- WatsynView::WatsynView( Instrument * _instrument,
- QWidget * _parent ) :
- InstrumentViewFixedSize( _instrument, _parent )
- {
- setAutoFillBackground( true );
- QPalette pal;
- pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap( "artwork" ) );
- setPalette( pal );
- // knobs... lots of em
- makeknob( a1_volKnob, 130, A1ROW, tr( "Volume" ), "%", "aKnob" )
- makeknob( a2_volKnob, 130, A2ROW, tr( "Volume" ), "%", "aKnob" )
- makeknob( b1_volKnob, 130, B1ROW, tr( "Volume" ), "%", "bKnob" )
- makeknob( b2_volKnob, 130, B2ROW, tr( "Volume" ), "%", "bKnob" )
- makeknob( a1_panKnob, 154, A1ROW, tr( "Panning" ), "", "aKnob" )
- makeknob( a2_panKnob, 154, A2ROW, tr( "Panning" ), "", "aKnob" )
- makeknob( b1_panKnob, 154, B1ROW, tr( "Panning" ), "", "bKnob" )
- makeknob( b2_panKnob, 154, B2ROW, tr( "Panning" ), "", "bKnob" )
- makeknob( a1_multKnob, 178, A1ROW, tr( "Freq. multiplier" ), "/8", "aKnob" )
- makeknob( a2_multKnob, 178, A2ROW, tr( "Freq. multiplier" ), "/8", "aKnob" )
- makeknob( b1_multKnob, 178, B1ROW, tr( "Freq. multiplier" ), "/8", "bKnob" )
- makeknob( b2_multKnob, 178, B2ROW, tr( "Freq. multiplier" ), "/8", "bKnob" )
- makeknob( a1_ltuneKnob, 202, A1ROW, tr( "Left detune" ), tr( " cents" ), "aKnob" )
- makeknob( a2_ltuneKnob, 202, A2ROW, tr( "Left detune" ), tr( " cents" ), "aKnob" )
- makeknob( b1_ltuneKnob, 202, B1ROW, tr( "Left detune" ), tr( " cents" ), "bKnob" )
- makeknob( b2_ltuneKnob, 202, B2ROW, tr( "Left detune" ), tr( " cents" ), "bKnob" )
- makeknob( a1_rtuneKnob, 226, A1ROW, tr( "Right detune" ), tr( " cents" ), "aKnob" )
- makeknob( a2_rtuneKnob, 226, A2ROW, tr( "Right detune" ), tr( " cents" ), "aKnob" )
- makeknob( b1_rtuneKnob, 226, B1ROW, tr( "Right detune" ), tr( " cents" ), "bKnob" )
- makeknob( b2_rtuneKnob, 226, B2ROW, tr( "Right detune" ), tr( " cents" ), "bKnob" )
- makeknob( m_abmixKnob, 4, 3, tr( "A-B Mix" ), "", "mixKnob" )
- makeknob( m_envAmtKnob, 88, 3, tr( "Mix envelope amount" ), "", "mixenvKnob" )
- maketsknob( m_envAttKnob, 88, A1ROW, tr( "Mix envelope attack" ), " ms", "mixenvKnob" )
- maketsknob( m_envHoldKnob, 88, A2ROW, tr( "Mix envelope hold" ), " ms", "mixenvKnob" )
- maketsknob( m_envDecKnob, 88, B1ROW, tr( "Mix envelope decay" ), " ms", "mixenvKnob" )
- makeknob( m_xtalkKnob, 88, B2ROW, tr( "Crosstalk" ), "", "xtalkKnob" )
- // let's set volume knobs
- a1_volKnob -> setVolumeKnob( true );
- a2_volKnob -> setVolumeKnob( true );
- b1_volKnob -> setVolumeKnob( true );
- b2_volKnob -> setVolumeKnob( true );
- m_abmixKnob -> setFixedSize( 31, 31 );
- // button groups next.
- // graph select buttons
- PixmapButton * a1_selectButton = new PixmapButton( this, nullptr );
- a1_selectButton -> move( 4, 121 );
- a1_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "a1_active" ) );
- a1_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "a1_inactive" ) );
- ToolTip::add( a1_selectButton, tr( "Select oscillator A1") );
- PixmapButton * a2_selectButton = new PixmapButton( this, nullptr );
- a2_selectButton -> move( 44, 121 );
- a2_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "a2_active" ) );
- a2_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "a2_inactive" ) );
- ToolTip::add( a2_selectButton, tr( "Select oscillator A2") );
- PixmapButton * b1_selectButton = new PixmapButton( this, nullptr );
- b1_selectButton -> move( 84, 121 );
- b1_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "b1_active" ) );
- b1_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "b1_inactive" ) );
- ToolTip::add( b1_selectButton, tr( "Select oscillator B1") );
- PixmapButton * b2_selectButton = new PixmapButton( this, nullptr );
- b2_selectButton -> move( 124, 121 );
- b2_selectButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "b2_active" ) );
- b2_selectButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "b2_inactive" ) );
- ToolTip::add( b2_selectButton, tr( "Select oscillator B2") );
- m_selectedGraphGroup = new automatableButtonGroup( this );
- m_selectedGraphGroup -> addButton( a1_selectButton );
- m_selectedGraphGroup -> addButton( a2_selectButton );
- m_selectedGraphGroup -> addButton( b1_selectButton );
- m_selectedGraphGroup -> addButton( b2_selectButton );
- WatsynInstrument * w = castModel<WatsynInstrument>();
- m_selectedGraphGroup -> setModel( &w -> m_selectedGraph);
- // A-modulation button group
- PixmapButton * amod_mixButton = new PixmapButton( this, nullptr );
- amod_mixButton -> move( 4, 50 );
- amod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "amix_active" ) );
- amod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "amix_inactive" ) );
- ToolTip::add( amod_mixButton, tr( "Mix output of A2 to A1" ) );
- PixmapButton * amod_amButton = new PixmapButton( this, nullptr );
- amod_amButton -> move( 4, 66 );
- amod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "aam_active" ) );
- amod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "aam_inactive" ) );
- ToolTip::add( amod_amButton, tr( "Modulate amplitude of A1 by output of A2" ) );
- PixmapButton * amod_rmButton = new PixmapButton( this, nullptr );
- amod_rmButton -> move( 4, 82 );
- amod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "arm_active" ) );
- amod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "arm_inactive" ) );
- ToolTip::add( amod_rmButton, tr( "Ring modulate A1 and A2" ) );
- PixmapButton * amod_pmButton = new PixmapButton( this, nullptr );
- amod_pmButton -> move( 4, 98 );
- amod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "apm_active" ) );
- amod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "apm_inactive" ) );
- ToolTip::add( amod_pmButton, tr( "Modulate phase of A1 by output of A2" ) );
- m_aModGroup = new automatableButtonGroup( this );
- m_aModGroup -> addButton( amod_mixButton );
- m_aModGroup -> addButton( amod_amButton );
- m_aModGroup -> addButton( amod_rmButton );
- m_aModGroup -> addButton( amod_pmButton );
- // B-modulation button group
- PixmapButton * bmod_mixButton = new PixmapButton( this, nullptr );
- bmod_mixButton -> move( 44, 50 );
- bmod_mixButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bmix_active" ) );
- bmod_mixButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bmix_inactive" ) );
- ToolTip::add( bmod_mixButton, tr( "Mix output of B2 to B1" ) );
- PixmapButton * bmod_amButton = new PixmapButton( this, nullptr );
- bmod_amButton -> move( 44, 66 );
- bmod_amButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bam_active" ) );
- bmod_amButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bam_inactive" ) );
- ToolTip::add( bmod_amButton, tr( "Modulate amplitude of B1 by output of B2" ) );
- PixmapButton * bmod_rmButton = new PixmapButton( this, nullptr );
- bmod_rmButton -> move( 44, 82 );
- bmod_rmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "brm_active" ) );
- bmod_rmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "brm_inactive" ) );
- ToolTip::add( bmod_rmButton, tr( "Ring modulate B1 and B2" ) );
- PixmapButton * bmod_pmButton = new PixmapButton( this, nullptr );
- bmod_pmButton -> move( 44, 98 );
- bmod_pmButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "bpm_active" ) );
- bmod_pmButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "bpm_inactive" ) );
- ToolTip::add( bmod_pmButton, tr( "Modulate phase of B1 by output of B2" ) );
- m_bModGroup = new automatableButtonGroup( this );
- m_bModGroup -> addButton( bmod_mixButton );
- m_bModGroup -> addButton( bmod_amButton );
- m_bModGroup -> addButton( bmod_rmButton );
- m_bModGroup -> addButton( bmod_pmButton );
- // graph widgets
- pal = QPalette();
- pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap("wavegraph") );
- // a1 graph
- a1_graph = new Graph( this, Graph::LinearStyle, 224, 105 );
- a1_graph->move( 4, 141 );
- a1_graph->setAutoFillBackground( true );
- a1_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) );
- ToolTip::add( a1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
- a1_graph->setPalette( pal );
- // a2 graph
- a2_graph = new Graph( this, Graph::LinearStyle, 224, 105 );
- a2_graph->move( 4, 141 );
- a2_graph->setAutoFillBackground( true );
- a2_graph->setGraphColor( QColor( 0x43, 0xb2, 0xff ) );
- ToolTip::add( a2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
- a2_graph->setPalette( pal );
- // b1 graph
- b1_graph = new Graph( this, Graph::LinearStyle, 224, 105 );
- b1_graph->move( 4, 141 );
- b1_graph->setAutoFillBackground( true );
- b1_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) );
- ToolTip::add( b1_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
- b1_graph->setPalette( pal );
- // b2 graph
- b2_graph = new Graph( this, Graph::LinearStyle, 224, 105 );
- b2_graph->move( 4, 141 );
- b2_graph->setAutoFillBackground( true );
- b2_graph->setGraphColor( QColor( 0xfc, 0x54, 0x31 ) );
- ToolTip::add( b2_graph, tr ( "Draw your own waveform here by dragging your mouse on this graph." ) );
- b2_graph->setPalette( pal );
- // misc pushbuttons
- // waveform modifications
- m_loadButton = new PixmapButton( this, tr( "Load waveform" ) );
- m_loadButton -> move ( 173, 121 );
- m_loadButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "load_active" ) );
- m_loadButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "load_inactive" ) );
- ToolTip::add( m_loadButton, tr( "Load a waveform from a sample file" ) );
- m_phaseLeftButton = new PixmapButton( this, tr( "Phase left" ) );
- m_phaseLeftButton -> move ( 193, 121 );
- m_phaseLeftButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_active" ) );
- m_phaseLeftButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phl_inactive" ) );
- ToolTip::add( m_phaseLeftButton, tr( "Shift phase by -15 degrees" ) );
- m_phaseRightButton = new PixmapButton( this, tr( "Phase right" ) );
- m_phaseRightButton -> move ( 210, 121 );
- m_phaseRightButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_active" ) );
- m_phaseRightButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "phr_inactive" ) );
- ToolTip::add( m_phaseRightButton, tr( "Shift phase by +15 degrees" ) );
- m_normalizeButton = new PixmapButton( this, tr( "Normalize" ) );
- m_normalizeButton -> move ( 230, 121 );
- m_normalizeButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_active" ) );
- m_normalizeButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "norm_inactive" ) );
- ToolTip::add( m_normalizeButton, tr( "Normalize" ) );
- m_invertButton = new PixmapButton( this, tr( "Invert" ) );
- m_invertButton -> move ( 230, 138 );
- m_invertButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_active" ) );
- m_invertButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "inv_inactive" ) );
- ToolTip::add( m_invertButton, tr( "Invert" ) );
- m_smoothButton = new PixmapButton( this, tr( "Smooth" ) );
- m_smoothButton -> move ( 230, 155 );
- m_smoothButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_active" ) );
- m_smoothButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "smooth_inactive" ) );
- ToolTip::add( m_smoothButton, tr( "Smooth" ) );
- // waveforms
- m_sinWaveButton = new PixmapButton( this, tr( "Sine wave" ) );
- m_sinWaveButton -> move ( 230, 176 );
- m_sinWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_active" ) );
- m_sinWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sin_inactive" ) );
- ToolTip::add( m_sinWaveButton, tr( "Sine wave" ) );
- m_triWaveButton = new PixmapButton( this, tr( "Triangle wave" ) );
- m_triWaveButton -> move ( 230, 194 );
- m_triWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_active" ) );
- m_triWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "tri_inactive" ) );
- ToolTip::add( m_triWaveButton, tr( "Triangle wave" ) );
- m_sawWaveButton = new PixmapButton( this, tr( "Triangle wave" ) );
- m_sawWaveButton -> move ( 230, 212 );
- m_sawWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_active" ) );
- m_sawWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "saw_inactive" ) );
- ToolTip::add( m_sawWaveButton, tr( "Saw wave" ) );
- m_sqrWaveButton = new PixmapButton( this, tr( "Square wave" ) );
- m_sqrWaveButton -> move ( 230, 230 );
- m_sqrWaveButton -> setActiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_active" ) );
- m_sqrWaveButton -> setInactiveGraphic( PLUGIN_NAME::getIconPixmap( "sqr_inactive" ) );
- ToolTip::add( m_sqrWaveButton, tr( "Square wave" ) );
- connect( m_sinWaveButton, SIGNAL( clicked() ), this, SLOT( sinWaveClicked() ) );
- connect( m_triWaveButton, SIGNAL( clicked() ), this, SLOT( triWaveClicked() ) );
- connect( m_sawWaveButton, SIGNAL( clicked() ), this, SLOT( sawWaveClicked() ) );
- connect( m_sqrWaveButton, SIGNAL( clicked() ), this, SLOT( sqrWaveClicked() ) );
- connect( m_normalizeButton, SIGNAL( clicked() ), this, SLOT( normalizeClicked() ) );
- connect( m_invertButton, SIGNAL( clicked() ), this, SLOT( invertClicked() ) );
- connect( m_smoothButton, SIGNAL( clicked() ), this, SLOT( smoothClicked() ) );
- connect( m_phaseLeftButton, SIGNAL( clicked() ), this, SLOT( phaseLeftClicked() ) );
- connect( m_phaseRightButton, SIGNAL( clicked() ), this, SLOT( phaseRightClicked() ) );
- connect( m_loadButton, SIGNAL( clicked() ), this, SLOT( loadClicked() ) );
- connect( a1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
- connect( a2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
- connect( b1_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
- connect( b2_selectButton, SIGNAL( clicked() ), this, SLOT( updateLayout() ) );
- updateLayout();
- }
- WatsynView::~WatsynView()
- {
- }
- void WatsynView::updateLayout()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->show();
- a2_graph->hide();
- b1_graph->hide();
- b2_graph->hide();
- break;
- case A2_OSC:
- a1_graph->hide();
- a2_graph->show();
- b1_graph->hide();
- b2_graph->hide();
- break;
- case B1_OSC:
- a1_graph->hide();
- a2_graph->hide();
- b1_graph->show();
- b2_graph->hide();
- break;
- case B2_OSC:
- a1_graph->hide();
- a2_graph->hide();
- b1_graph->hide();
- b2_graph->show();
- break;
- }
- }
- void WatsynView::sinWaveClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->setWaveToSine();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->setWaveToSine();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->setWaveToSine();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->setWaveToSine();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::triWaveClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->setWaveToTriangle();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->setWaveToTriangle();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->setWaveToTriangle();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->setWaveToTriangle();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::sawWaveClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->setWaveToSaw();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->setWaveToSaw();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->setWaveToSaw();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->setWaveToSaw();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::sqrWaveClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->setWaveToSquare();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->setWaveToSquare();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->setWaveToSquare();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->setWaveToSquare();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::normalizeClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->normalize();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->normalize();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->normalize();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->normalize();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::invertClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->invert();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->invert();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->invert();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->invert();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::smoothClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->smooth();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->smooth();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->smooth();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->smooth();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::phaseLeftClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->shiftPhase( -15 );
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->shiftPhase( -15 );
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->shiftPhase( -15 );
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->shiftPhase( -15 );
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::phaseRightClicked()
- {
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->shiftPhase( 15 );
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->shiftPhase( 15 );
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->shiftPhase( 15 );
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->shiftPhase( 15 );
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::loadClicked()
- {
- QString fileName;
- switch( m_selectedGraphGroup->model()->value() )
- {
- case A1_OSC:
- a1_graph->model()->setWaveToUser();
- Engine::getSong()->setModified();
- break;
- case A2_OSC:
- a2_graph->model()->setWaveToUser();
- Engine::getSong()->setModified();
- break;
- case B1_OSC:
- b1_graph->model()->setWaveToUser();
- Engine::getSong()->setModified();
- break;
- case B2_OSC:
- b2_graph->model()->setWaveToUser();
- Engine::getSong()->setModified();
- break;
- }
- }
- void WatsynView::modelChanged()
- {
- WatsynInstrument * w = castModel<WatsynInstrument>();
- a1_volKnob -> setModel( &w -> a1_vol );
- a2_volKnob -> setModel( &w -> a2_vol );
- b1_volKnob -> setModel( &w -> b1_vol );
- b2_volKnob -> setModel( &w -> b2_vol );
- a1_panKnob -> setModel( &w -> a1_pan );
- a2_panKnob -> setModel( &w -> a2_pan );
- b1_panKnob -> setModel( &w -> b1_pan );
- b2_panKnob -> setModel( &w -> b2_pan );
- a1_multKnob -> setModel( &w -> a1_mult );
- a2_multKnob -> setModel( &w -> a2_mult );
- b1_multKnob -> setModel( &w -> b1_mult );
- b2_multKnob -> setModel( &w -> b2_mult );
- a1_ltuneKnob -> setModel( &w -> a1_ltune );
- a2_ltuneKnob -> setModel( &w -> a2_ltune );
- b1_ltuneKnob -> setModel( &w -> b1_ltune );
- b2_ltuneKnob -> setModel( &w -> b2_ltune );
- a1_rtuneKnob -> setModel( &w -> a1_rtune );
- a2_rtuneKnob -> setModel( &w -> a2_rtune );
- b1_rtuneKnob -> setModel( &w -> b1_rtune );
- b2_rtuneKnob -> setModel( &w -> b2_rtune );
- m_abmixKnob -> setModel( &w -> m_abmix );
- m_selectedGraphGroup -> setModel( &w -> m_selectedGraph );
- m_aModGroup -> setModel( &w -> m_amod );
- m_bModGroup -> setModel( &w -> m_bmod );
- a1_graph -> setModel( &w -> a1_graph );
- a2_graph -> setModel( &w -> a2_graph );
- b1_graph -> setModel( &w -> b1_graph );
- b2_graph -> setModel( &w -> b2_graph );
- m_envAmtKnob -> setModel( &w -> m_envAmt );
- m_envAttKnob -> setModel( &w -> m_envAtt );
- m_envHoldKnob -> setModel( &w -> m_envHold );
- m_envDecKnob -> setModel( &w -> m_envDec );
- m_xtalkKnob -> setModel( &w -> m_xtalk );
- }
- extern "C"
- {
- // necessary for getting instance out of shared lib
- PLUGIN_EXPORT Plugin * lmms_plugin_main( Model *m, void * )
- {
- return( new WatsynInstrument( static_cast<InstrumentTrack *>( m ) ) );
- }
- }
|