|
- #include "mscHack.hpp"
- //#include "mscHack_Controls.hpp"
- #include "dsp/digital.hpp"
- //#include "CLog.h"
-
- namespace rack_plugin_mscHack {
-
- #define MAX_ARP_PATTERNS 16
- #define MAX_ARP_NOTES 7
- #define SUBSTEP_PER_NOTE 3
-
- #define SEMI ( 1.0f / 12.0f )
- #define TRIG_OFF_TICKS 10
-
- #define ARP_OFF 0
- #define ARP_ON 1
- #define ARP_REST 2
-
- typedef struct
- {
- int notesused;
- int notes [ MAX_ARP_NOTES ];
- int onoffsel[ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ];
- int lensel [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ];
- int lenmod [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ];
- int legato [ MAX_ARP_NOTES ];
- int glide [ MAX_ARP_NOTES ];
- int mode;
- int oct;
-
- }ARP_PATTERN_STRUCT;
-
- typedef struct
- {
- bool bPending;
- int pat;
- }ARP_PHRASE_CHANGE_STRUCT;
-
- //------------------------------------------------------
- // sliding window average
- /*#define AVG_ARRAY_LEN 4
- #define AVG_AND (AVG_ARRAY_LEN - 1)
-
- typedef struct
- {
- int count;
- int avg[ AVG_ARRAY_LEN ];
- int tot;
- }SLIDING_AVG_STRUCT;*/
-
- typedef struct
- {
- // track in clk bpm
- //SLIDING_AVG_STRUCT Avg;
- int tickcount;
- float ftickspersec;
- float fbpm;
-
- // track sync tick
- float fsynclen;
- float fsynccount;
-
- bool bClockReset;
- int IgnoreClockCount;
-
- }MAIN_SYNC_CLOCK;
-
- typedef struct
- {
- // timing
- bool bTrig;
- int pat;
- int used;
-
- int step;
- int virtstep;
-
- ARP_PHRASE_CHANGE_STRUCT pending;
-
- // track current arp trig
- int nextcount;
- bool bNextTrig;
-
- // glide
- float fglideInc;
- int glideCount;
- float fglide;
- float fLastNotePlayed;
- bool bWasLastNotePlayed;
-
- // voct out
- float fCvStartOut = 0;
- float fCvEndOut = 0;
-
- }PAT_STEP_STRUCT;
-
- //-----------------------------------------------------
- // Module Definition
- //
- //-----------------------------------------------------
- struct ARP700 : Module
- {
- enum ParamIds
- {
- nPARAMS
- };
-
- enum InputIds
- {
- IN_CLOCK_TRIG,
- IN_VOCT_OFF,
- IN_PROG_CHANGE,
- IN_CLOCK_RESET,
- nINPUTS
- };
-
- enum OutputIds
- {
- OUT_TRIG,
- OUT_VOCTS,
- nOUTPUTS
- };
-
- enum NoteStates
- {
- STATE_NOTE_OFF,
- STATE_NOTE_ON,
- STATE_NOTE_REST,
- STATE_TRIG_OFF
- };
-
- CLog lg;
- bool m_bInitialized = false;
-
- // Contructor
- ARP700() : Module(nPARAMS, nINPUTS, nOUTPUTS, 0){}
-
- // pattern
- ARP_PATTERN_STRUCT m_PatternSave[ MAX_ARP_PATTERNS ] = {};
- PAT_STEP_STRUCT m_PatCtrl = {};
-
- SchmittTrigger m_SchTrigPatternChange;
- PatternSelectStrip *m_pPatternSelect = NULL;
-
- bool m_bCopySrc = false;
-
- // pattern buttons
- MyLEDButtonStrip *m_pButtonOnOff [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ] = {};
- MyLEDButtonStrip *m_pButtonLen [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ] = {};
- MyLEDButtonStrip *m_pButtonLenMod[ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ] = {};
- MyLEDButton *m_pButtonGlide [ MAX_ARP_NOTES ] = {};
- MyLEDButton *m_pButtonTrig [ MAX_ARP_NOTES ] = {};
- MyLEDButtonStrip *m_plastbut = NULL;
- MyLEDButton *m_pButtonCopy= NULL;
-
- // clock
- SchmittTrigger m_SchTrigClk;
- MAIN_SYNC_CLOCK m_Clock;
-
- // global triggers
- SchmittTrigger m_SchTrigGlobalClkReset;
- bool m_GlobalClkResetPending = false;
-
- // keyboard
- Keyboard_3Oct_Widget *pKeyboardWidget = NULL;
- float m_fKeyNotes[ 37 ];
- float m_VoctOffsetIn = 0;
-
- // octave
- MyLEDButtonStrip *m_pButtonOctaveSelect = NULL;
-
- // pause
- bool m_bPauseState = false;
- MyLEDButton *m_pButtonPause;
-
- // mode
- MyLEDButtonStrip *m_pButtonMode = 0;
-
- // Overrides
- void step() override;
- void JsonParams( bool bTo, json_t *root);
- json_t* toJson() override;
- void fromJson(json_t *rootJ) override;
- void onRandomize() override;
- void onReset() override;
-
- void SetPatternSteps( int nSteps );
- void SetOut( void );
- void ChangePattern( int index, bool bForce );
- void SetPendingPattern( int phrase );
- void ArpStep( bool bReset );
- void Copy( bool bOn );
- };
-
- //-----------------------------------------------------
- // Procedure: ARP700_ModeSelect
- //-----------------------------------------------------
- void ARP700_ModeSelect( void *pClass, int id, int nbutton, bool bOn )
- {
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].mode = nbutton;
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_NoteOnOff
- //-----------------------------------------------------
- void ARP700_NoteOnOff( void *pClass, int id, int nbutton, bool bOn )
- {
- int note, param;
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
-
- note = id / SUBSTEP_PER_NOTE;
- param = id - ( SUBSTEP_PER_NOTE * note );
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].onoffsel[ note ][ param ] = nbutton;
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_NoteLenSelect
- //-----------------------------------------------------
- void ARP700_NoteLenSelect( void *pClass, int id, int nbutton, bool bOn )
- {
- int note, param;
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
-
- note = id / SUBSTEP_PER_NOTE;
- param = id - ( SUBSTEP_PER_NOTE * note );
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].lensel[ note ][ param ] = nbutton;
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_OctSelect
- //-----------------------------------------------------
- void ARP700_OctSelect( void *pClass, int id, int nbutton, bool bOn )
- {
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
-
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].oct = nbutton;
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_mod
- //-----------------------------------------------------
- void ARP700_mod( void *pClass, int id, int nbutton, bool bOn )
- {
- int note, param;
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
-
- note = id / SUBSTEP_PER_NOTE;
- param = id - ( SUBSTEP_PER_NOTE * note );
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].lenmod[ note ][ param ] = nbutton;
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_Pause
- //-----------------------------------------------------
- void ARP700_Pause( void *pClass, int id, bool bOn )
- {
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
- mymodule->m_bPauseState = bOn;
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_Copy
- //-----------------------------------------------------
- void ARP700_Copy( void *pClass, int id, bool bOn )
- {
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
- mymodule->Copy( bOn );
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_Glide
- //-----------------------------------------------------
- void ARP700_Glide( void *pClass, int id, bool bOn )
- {
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].glide[ id ] = bOn;
- //mymodule->lg.f("Glide[ %d ] = %d\n", id, bOn );
- }
-
- //-----------------------------------------------------
- // Procedure: ARP700_Trig
- //-----------------------------------------------------
- void ARP700_Trig( void *pClass, int id, bool bOn )
- {
- ARP700 *mymodule;
- mymodule = (ARP700*)pClass;
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].legato[ id ] = bOn;
- //mymodule->lg.f("Legato[ %d ] = %d\n", id, bOn );
- }
-
- //-----------------------------------------------------
- // Procedure: NoteChangeCallback
- //
- //-----------------------------------------------------
- void ARP700_Widget_NoteChangeCallback ( void *pClass, int kb, int notepressed, int *pnotes, bool bOn, int button )
- {
- ARP700 *mymodule = (ARP700 *)pClass;
-
- if( !pClass )
- return;
-
- memcpy( mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].notes, pnotes, sizeof( int ) * MAX_ARP_NOTES );
- mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].notesused = mymodule->pKeyboardWidget->m_nKeysOn;
- }
-
- //-----------------------------------------------------
- // Procedure: PatternChangeCallback
- //
- //-----------------------------------------------------
- void ARP700_Widget_PatternChangeCallback ( void *pClass, int kb, int pat, int max )
- {
- ARP700 *mymodule = (ARP700 *)pClass;
-
- if( !mymodule || !mymodule->m_bInitialized )
- return;
-
- if( mymodule->m_PatCtrl.pat != pat )
- {
- if( !mymodule->m_bPauseState && mymodule->inputs[ ARP700::IN_CLOCK_TRIG ].active )
- mymodule->SetPendingPattern( pat );
- else
- mymodule->ChangePattern( pat, false );
-
- }
- else if( mymodule->m_PatCtrl.used != max )
- mymodule->SetPatternSteps( max );
- }
-
- //-----------------------------------------------------
- // Procedure: Widget
- //
- //-----------------------------------------------------
-
- struct ARP700_Widget : ModuleWidget {
- ARP700_Widget( ARP700 *module );
- };
-
- ARP700_Widget::ARP700_Widget( ARP700 *module ) : ModuleWidget(module)
- {
- int x, y, note, param;
-
- box.size = Vec( 15*27, 380);
-
- {
- SVGPanel *panel = new SVGPanel();
- panel->box.size = box.size;
- panel->setBackground(SVG::load(assetPlugin(plugin, "res/ARP700.svg")));
- addChild(panel);
- }
-
- for( int i = 0; i < 37; i++ )
- module->m_fKeyNotes[ i ] = (float)i * SEMI;
-
- //module->lg.Open("ARP700.txt");
-
- // pause button
- module->m_pButtonPause = new MyLEDButton( 75, 22, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, 0, module, ARP700_Pause );
- addChild( module->m_pButtonPause );
-
- // copy button
- module->m_pButtonCopy = new MyLEDButton( 307, 22, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_SWITCH, 0, module, ARP700_Copy );
- addChild( module->m_pButtonCopy );
-
- // keyboard widget
- module->pKeyboardWidget = new Keyboard_3Oct_Widget( 75, 38, MAX_ARP_NOTES, 0, DWRGB( 255, 128, 64 ), module, ARP700_Widget_NoteChangeCallback, &module->lg );
- addChild( module->pKeyboardWidget );
-
- // octave select
- module->m_pButtonOctaveSelect = new MyLEDButtonStrip( 307, 104, 11, 11, 3, 8.0, 4, false, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, 0, module, ARP700_OctSelect );
- addChild( module->m_pButtonOctaveSelect );
-
- // pattern selects
- module->m_pPatternSelect = new PatternSelectStrip( 75, 104, 9, 7, DWRGB( 200, 200, 200 ), DWRGB( 40, 40, 40 ), DWRGB( 112, 104, 102 ), DWRGB( 40, 40, 40 ), MAX_ARP_PATTERNS, 0, module, ARP700_Widget_PatternChangeCallback );
- addChild( module->m_pPatternSelect );
-
- x = 60;
-
- for( note = 0; note < MAX_ARP_NOTES; note++ )
- {
- for( param = 0; param < SUBSTEP_PER_NOTE; param++ )
- {
- y = 140;
-
- module->m_pButtonOnOff[ note ][ param ] = new MyLEDButtonStrip( x, y, 12, 12, 2, 10.0, 3, true, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, (note * SUBSTEP_PER_NOTE ) + param, module, ARP700_NoteOnOff );
- addChild( module->m_pButtonOnOff[ note ][ param ] );
-
- module->m_pButtonOnOff[ note ][ param ]->SetLEDCol( 1, DWRGB( 0, 255, 0 ) );
- module->m_pButtonOnOff[ note ][ param ]->SetLEDCol( 2, DWRGB( 255, 255, 0 ) );
-
- y += 43;
-
- module->m_pButtonLen[ note ][ param ] = new MyLEDButtonStrip( x, y, 12, 12, 2, 10.0, 6, true, DWRGB( 180, 180, 180 ), DWRGB( 255, 128, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, (note * SUBSTEP_PER_NOTE ) + param, module, ARP700_NoteLenSelect );
- addChild( module->m_pButtonLen[ note ][ param ] );
-
- y += 89;
-
- module->m_pButtonLenMod[ note ][ param ] = new MyLEDButtonStrip( x, y, 12, 12, 2, 10.0, 3, true, DWRGB( 180, 180, 180 ), DWRGB( 255, 128, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE_WOFF, (note * SUBSTEP_PER_NOTE ) + param, module, ARP700_mod );
- addChild( module->m_pButtonLenMod[ note ][ param ] );
-
- if( param == 1 )
- {
- y += 43;
-
- module->m_pButtonGlide[ note ] = new MyLEDButton( x, y, 12, 12, 10.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_SWITCH, note, module, ARP700_Glide );
- addChild( module->m_pButtonGlide[ note ] );
-
- y += 16;
-
- module->m_pButtonTrig[ note ] = new MyLEDButton( x, y, 12, 12, 10.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_SWITCH, note, module, ARP700_Trig );
- addChild( module->m_pButtonTrig[ note ] );
- }
-
- x += 14;
- }
-
- x += 5;
- }
-
- // clock trigger
- addInput(Port::create<MyPortInSmall>( Vec( 44, 21 ), Port::INPUT, module, ARP700::IN_CLOCK_TRIG ) );
-
- // VOCT offset input
- addInput(Port::create<MyPortInSmall>( Vec( 44, 52 ), Port::INPUT, module, ARP700::IN_VOCT_OFF ) );
-
- // prog change trigger
- addInput(Port::create<MyPortInSmall>( Vec( 44, 102 ), Port::INPUT, module, ARP700::IN_PROG_CHANGE ) );
-
- // outputs
- addOutput(Port::create<MyPortOutSmall>( Vec( 365, 38 ), Port::OUTPUT, module, ARP700::OUT_VOCTS ) );
- addOutput(Port::create<MyPortOutSmall>( Vec( 365, 79 ), Port::OUTPUT, module, ARP700::OUT_TRIG ) );
-
- // reset inputs
- addInput(Port::create<MyPortInSmall>( Vec( 14, 21 ), Port::INPUT, module, ARP700::IN_CLOCK_RESET ) );
-
- // mode buttons
- module->m_pButtonMode = new MyLEDButtonStrip( 154, 360, 12, 12, 7, 10.0, 7, false, DWRGB( 180, 180, 180 ), DWRGB( 255, 255, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, 0, module, ARP700_ModeSelect );
- addChild( module->m_pButtonMode );
-
- addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
- addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
- addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
- addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
-
- module->m_Clock.fsynclen = 2.0 * 48.0; // default to 120bpm
- module->m_Clock.IgnoreClockCount = 2;
- module->m_bInitialized = true;
-
- module->onReset();
- }
-
- //-----------------------------------------------------
- // Procedure: JsonParams
- //
- //-----------------------------------------------------
- void ARP700::JsonParams( bool bTo, json_t *root)
- {
- JsonDataBool ( bTo, "m_bPauseState", root, &m_bPauseState, 1 );
- JsonDataInt ( bTo, "m_CurrentPattern", root, &m_PatCtrl.pat, 1 );
- JsonDataInt ( bTo, "m_PatternSave", root, (int*)m_PatternSave, sizeof( m_PatternSave ) / 4 );
- JsonDataInt ( bTo, "m_PatternsUsed", root, &m_PatCtrl.used, 1 );
- }
-
- //-----------------------------------------------------
- // Procedure: toJson
- //
- //-----------------------------------------------------
- json_t *ARP700::toJson()
- {
- json_t *root = json_object();
-
- if( !root )
- return NULL;
-
- JsonParams( TOJSON, root );
-
- return root;
- }
-
- //-----------------------------------------------------
- // Procedure: fromJson
- //
- //-----------------------------------------------------
- void ARP700::fromJson( json_t *root )
- {
- JsonParams( FROMJSON, root );
-
- m_pButtonPause->Set( m_bPauseState );
- pKeyboardWidget->setkey( m_PatternSave[ m_PatCtrl.pat ].notes );
-
- ChangePattern( m_PatCtrl.pat, true );
-
- ArpStep( true );
- }
-
- //-----------------------------------------------------
- // Procedure: reset
- //
- //-----------------------------------------------------
- void ARP700::onReset()
- {
- int pat, note;
-
- if( !m_bInitialized )
- return;
-
- m_pButtonOctaveSelect->Set( 0, true );
-
- m_PatCtrl.fCvStartOut = 0;
- m_PatCtrl.fCvEndOut = 0;
- memset( m_PatternSave, 0, sizeof(m_PatternSave) );
-
- for( pat = 0; pat < MAX_ARP_PATTERNS; pat++ )
- {
- for( note = 0; note < MAX_ARP_NOTES; note++ )
- m_PatternSave[ pat ].notes[ note ] = -1;
- }
-
- SetPatternSteps( MAX_ARP_PATTERNS - 1 );
- ChangePattern( 0, true );
- }
-
- //-----------------------------------------------------
- // Procedure: randomize
- //
- //-----------------------------------------------------
- void ARP700::onRandomize()
- {
- }
-
- //-----------------------------------------------------
- // Procedure: SetPhraseSteps
- //
- //-----------------------------------------------------
- void ARP700::SetPatternSteps( int nSteps )
- {
- if( nSteps < 0 || nSteps >= MAX_ARP_PATTERNS )
- nSteps = 0;
-
- m_PatCtrl.used = nSteps;
- }
-
- //-----------------------------------------------------
- // Procedure: SetOut
- //
- //-----------------------------------------------------
- void ARP700::SetOut( void )
- {
- int note = 0, nstep, substep;
- float foct;
-
- m_VoctOffsetIn = inputs[ IN_VOCT_OFF ].normalize( 0.0 );
-
- nstep = m_PatCtrl.step / SUBSTEP_PER_NOTE;
- substep = m_PatCtrl.step - ( nstep * SUBSTEP_PER_NOTE );
-
- if( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ nstep ][ substep ] == ARP_ON )
- {
- note = m_PatternSave[ m_PatCtrl.pat ].notes[ nstep ];
- pKeyboardWidget->setkeyhighlight( note );
- }
- else
- return;
-
- if( note > 36 || note < 0 )
- note = 0;
-
- foct = (float)m_PatternSave[ m_PatCtrl.pat ].oct;
-
- m_PatCtrl.fCvEndOut = foct + m_fKeyNotes[ note ] + m_VoctOffsetIn;
-
- // start glide note (last pattern note)
- if( m_PatCtrl.bWasLastNotePlayed )
- {
- m_PatCtrl.fCvStartOut = m_PatCtrl.fLastNotePlayed + m_VoctOffsetIn;
- }
- else
- {
- m_PatCtrl.bWasLastNotePlayed = true;
- m_PatCtrl.fCvStartOut = m_PatCtrl.fCvEndOut + m_VoctOffsetIn;
- }
-
- m_PatCtrl.fLastNotePlayed = m_PatCtrl.fCvEndOut + m_VoctOffsetIn;
-
- if( m_PatternSave[ m_PatCtrl.pat ].glide[ nstep ] )
- {
- // glide time
- m_PatCtrl.glideCount = 0.2 * engineGetSampleRate();
- m_PatCtrl.fglideInc = 1.0 / (float)m_PatCtrl.glideCount;
-
- m_PatCtrl.fglide = 1.0;
- }
- else
- {
- m_PatCtrl.fglide = 0.0;
- m_PatCtrl.glideCount = 0;
- }
- }
-
- //-----------------------------------------------------
- // Procedure: SetPendingPattern
- //
- //-----------------------------------------------------
- void ARP700::SetPendingPattern( int patin )
- {
- int pattern;
-
- if( patin < 0 || patin >= MAX_ARP_PATTERNS )
- pattern = ( m_PatCtrl.pat + 1 ) & 0x7;
- else
- pattern = patin;
-
- if( pattern > m_PatCtrl.used )
- pattern = 0;
-
- m_PatCtrl.pending.bPending = true;
- m_PatCtrl.pending.pat = pattern;
- m_pPatternSelect->SetPat( m_PatCtrl.pat, false );
- m_pPatternSelect->SetPat( pattern, true );
- }
-
- //-----------------------------------------------------
- // Procedure: Copy
- //
- //-----------------------------------------------------
- void ARP700::Copy( bool bOn )
- {
- if( !m_bPauseState || !bOn )
- {
- m_bCopySrc = false;
- m_pButtonCopy->Set( false );
- }
- else if( bOn )
- {
- m_bCopySrc = true;
- }
- }
-
- //-----------------------------------------------------
- // Procedure: ChangePattern
- //
- //-----------------------------------------------------
- void ARP700::ChangePattern( int index, bool bForce )
- {
- int note, param;
-
- if( !bForce && index == m_PatCtrl.pat )
- return;
-
- if( index < 0 )
- index = MAX_ARP_PATTERNS - 1;
- else if( index >= MAX_ARP_PATTERNS )
- index = 0;
-
- if( m_bCopySrc )
- {
- // do not copy if we are not paused
- if( m_bPauseState )
- {
- memcpy( &m_PatternSave[ index ], &m_PatternSave[ m_PatCtrl.pat ], sizeof(ARP_PATTERN_STRUCT) );
- m_pButtonCopy->Set( false );
- m_bCopySrc = false;
- }
- }
-
- m_PatCtrl.pat = index;
-
- for( note = 0; note < MAX_ARP_NOTES; note++ )
- {
- m_pButtonGlide[ note ]->Set( m_PatternSave[ m_PatCtrl.pat ].glide[ note ] );
- m_pButtonTrig[ note ]->Set( m_PatternSave[ m_PatCtrl.pat ].legato[ note ] );
-
- for( param = 0; param < SUBSTEP_PER_NOTE; param++ )
- {
- m_pButtonOnOff[ note ][ param ]->Set( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ note ][ param ], true );
- m_pButtonLen[ note ][ param ]->Set( m_PatternSave[ m_PatCtrl.pat ].lensel[ note ][ param ], true );
- m_pButtonLenMod[ note ][ param ]->Set( m_PatternSave[ m_PatCtrl.pat ].lenmod[ note ][ param ], true );
- }
- }
-
- m_pButtonOctaveSelect->Set( m_PatternSave[ m_PatCtrl.pat ].oct, true );
- m_pButtonMode->Set( m_PatternSave[ m_PatCtrl.pat ].mode, true );
- m_pPatternSelect->SetPat( index, false );
- m_pPatternSelect->SetMax( m_PatCtrl.used );
-
- // set keyboard keys
- pKeyboardWidget->setkey( m_PatternSave[ m_PatCtrl.pat ].notes );
- }
-
- //-----------------------------------------------------
- // Procedure: IncStep
- //
- //-----------------------------------------------------
- #define BASE_TICK_16th 48 // for 16th note
-
- const float fbasenotelen[ 6 ] = { BASE_TICK_16th * 4, BASE_TICK_16th * 2, BASE_TICK_16th, BASE_TICK_16th / 2, BASE_TICK_16th / 4, BASE_TICK_16th / 8};
-
- const int patmode[ 7 ][ 42 ] =
- {
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1 },
- { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1 },
- { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
- { 0, 20, 1, 19, 2, 18, 3, 17, 4, 16, 5, 15, 6, 14, 7, 13, 8, 12, 9, 11, 10, 10, 11, 9, 12, 8, 13, 7, 14, 6, 15, 5, 16, 4, 17, 3, 18, 2, 19, 1, 20, 0 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
- };
-
- void ARP700::ArpStep( bool bReset )
- {
- int i, nstep, substep, modestp;
-
- if( !m_PatternSave[ m_PatCtrl.pat ].notesused )
- {
- m_PatCtrl.virtstep = -1;
- m_PatCtrl.bTrig = false;
- return;
- }
- else
- {
- if( bReset )
- m_PatCtrl.virtstep = -1;
-
- // find next used step
- for( i = 0; i <= ( SUBSTEP_PER_NOTE * MAX_ARP_NOTES * 2 ); i++ )
- {
- m_PatCtrl.virtstep++;
-
- if( m_PatCtrl.virtstep >= ( SUBSTEP_PER_NOTE * MAX_ARP_NOTES * 2 ) )
- m_PatCtrl.virtstep = 0;
-
- if( m_PatternSave[ m_PatCtrl.pat ].mode == 6 )
- modestp = (int)( randomUniform() * 20.0f );
- else
- modestp = patmode[ m_PatternSave[ m_PatCtrl.pat ].mode ][ m_PatCtrl.virtstep ];
-
- if( modestp != -1 )
- {
- nstep = modestp / SUBSTEP_PER_NOTE;
- substep = modestp - ( nstep * SUBSTEP_PER_NOTE );
-
- if( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ nstep ][ substep ] != ARP_OFF )
- {
- m_PatCtrl.step = modestp;
- goto stepfound;
- }
- }
- else
- {
- m_PatCtrl.virtstep = -1;
- }
- }
- }
-
- // if we are here, no step was found
- m_PatCtrl.step = -1;
- m_PatCtrl.bTrig = false;
- return;
-
- stepfound:
-
- if( m_PatCtrl.step == 0 )
- {
- if( m_PatCtrl.pending.bPending )
- {
- m_PatCtrl.pending.bPending = false;
- ChangePattern( m_PatCtrl.pending.pat, true );
- }
- }
-
- nstep = m_PatCtrl.step / SUBSTEP_PER_NOTE;
- substep = m_PatCtrl.step - ( nstep * SUBSTEP_PER_NOTE );
-
- if( m_plastbut )
- m_plastbut->SetHiLightOn( -1 );
-
- m_pButtonLen[ nstep ][ substep ]->SetHiLightOn( m_PatternSave[ m_PatCtrl.pat ].lensel[ nstep ][ substep ] );
- m_plastbut = m_pButtonLen[ nstep ][ substep ];
-
- // next step length
- m_PatCtrl.nextcount = fbasenotelen[ m_PatternSave[ m_PatCtrl.pat ].lensel[ nstep ][ substep ] ];
-
- switch( m_PatternSave[ m_PatCtrl.pat ].lenmod[ nstep ][ substep ] )
- {
- case 1: // x2
- m_PatCtrl.nextcount *= 2;
- break;
- case 2: // dotted
- m_PatCtrl.nextcount += m_PatCtrl.nextcount / 2;
- break;
- case 3: // triplet
- m_PatCtrl.nextcount = m_PatCtrl.nextcount / 3;
- break;
- }
-
- // if this is note on return true
- if( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ nstep ][ substep ] == ARP_ON )
- {
- SetOut();
-
- if( m_PatternSave[ m_PatCtrl.pat ].legato[ nstep ] )
- m_PatCtrl.bTrig = false;
- else
- m_PatCtrl.bTrig = true;
- }
- }
-
- //-----------------------------------------------------
- // Procedure: step
- //
- //-----------------------------------------------------
- void ARP700::step()
- {
- bool bSyncTick = false, bResetClk = false;
-
- if( !m_bInitialized )
- return;
-
- if( !inputs[ IN_CLOCK_TRIG ].active )
- {
- outputs[ OUT_TRIG ].value = 0;
- m_Clock.tickcount = 0;
- m_Clock.fsynclen = 2.0 * 48.0; // default to 120bpm
- m_Clock.fsynccount = 0;
- m_Clock.IgnoreClockCount = 2;
-
- if( m_PatCtrl.pending.bPending )
- {
- m_PatCtrl.pending.bPending = false;
- ChangePattern( m_PatCtrl.pending.pat, false );
- }
-
- return;
- }
-
- // global clock reset
- m_Clock.bClockReset = ( m_SchTrigGlobalClkReset.process( inputs[ IN_CLOCK_RESET ].normalize( 0.0f ) ) );
-
- // pattern change trig
- if( !m_bPauseState && m_SchTrigPatternChange.process( inputs[ IN_PROG_CHANGE ].normalize( 0.0f ) ) )
- SetPendingPattern( -1 );
-
- // track clock period
- if( m_SchTrigClk.process( inputs[ IN_CLOCK_TRIG ].normalize( 0.0f ) ) || m_Clock.bClockReset )
- {
- if( m_Clock.bClockReset )
- {
- m_Clock.tickcount = 0;
- //ArpStep( true );
- m_Clock.bClockReset = false;
- m_Clock.IgnoreClockCount = 2;
- bResetClk = true;
- }
-
- if( m_Clock.tickcount && --m_Clock.IgnoreClockCount <= 0 )
- {
- m_Clock.IgnoreClockCount = 0;
- m_Clock.fsynclen = (float)( engineGetSampleRate() / (float)m_Clock.tickcount ) * 48.0;
- }
-
- m_Clock.fsynccount = 0;
- bSyncTick = true;
- m_Clock.tickcount = 0;
- }
- else
- {
- // keep track of sync tick (16th / 12 )
- m_Clock.fsynccount += m_Clock.fsynclen;
- if( m_Clock.fsynccount >= engineGetSampleRate() )
- {
- m_Clock.fsynccount = m_Clock.fsynccount - engineGetSampleRate();
- bSyncTick = true;
- }
- }
-
- m_Clock.tickcount++;
-
- if( m_bPauseState )
- {
- m_PatCtrl.bTrig = false;
-
- if( m_PatCtrl.pending.bPending )
- {
- m_PatCtrl.pending.bPending = false;
- ChangePattern( m_PatCtrl.pending.pat, false );
- }
- }
- else if( bSyncTick )
- {
- if( bResetClk )
- m_PatCtrl.nextcount = 0;
- else
- m_PatCtrl.nextcount--;
-
- // cut off note one tick early so they don't legato
- if( m_PatCtrl.nextcount == 1 )
- m_PatCtrl.bTrig = false;
-
- else if( m_PatCtrl.nextcount <= 0 )
- ArpStep( bResetClk );
- }
-
- outputs[ OUT_TRIG ].value = m_PatCtrl.bTrig ? CV_MAX : 0.0;
-
- if( --m_PatCtrl.glideCount > 0 )
- m_PatCtrl.fglide -= m_PatCtrl.fglideInc;
- else
- m_PatCtrl.fglide = 0.0;
-
- outputs[ OUT_VOCTS ].value = ( m_PatCtrl.fCvStartOut * m_PatCtrl.fglide ) + ( m_PatCtrl.fCvEndOut * ( 1.0 - m_PatCtrl.fglide ) );
-
- }
-
- } // namespace rack_plugin_mscHack
-
- using namespace rack_plugin_mscHack;
-
- RACK_PLUGIN_MODEL_INIT(mscHack, ARP700) {
- Model *modelARP700 = Model::create<ARP700, ARP700_Widget>( "mscHack", "ARP700", "ARP 700", SEQUENCER_TAG );
- return modelARP700;
- }
|