From f9527898df99be157763617ed7538ace8a4aa64c Mon Sep 17 00:00:00 2001 From: hirsch Date: Fri, 29 Jul 2016 15:40:45 -0400 Subject: [PATCH] Threaded build nominally working --- amp.cpp | 67 ++- amp.h | 102 ++-- amp_models.cpp | 2 + amp_models.h | 2 + constants.h | 21 - delay.cpp | 55 +- delay.h | 100 ++-- delay_models.cpp | 2 + delay_models.h | 2 + magic.cpp | 25 + magic.h | 31 +- mod.cpp | 53 +- mod.h | 150 +++--- mod_models.cpp | 2 + mod_models.h | 2 + mustang.cpp | 1289 +++++++++++++++++++++++++-------------------- mustang.h | 99 ++-- mustang_midi.cpp | 50 +- reverb.cpp | 36 +- reverb.h | 24 +- reverb_models.cpp | 4 + reverb_models.h | 8 + stomp.cpp | 53 +- stomp.h | 144 ++--- stomp_models.cpp | 2 + stomp_models.h | 2 + 26 files changed, 1237 insertions(+), 1090 deletions(-) create mode 100644 magic.cpp create mode 100644 reverb_models.cpp create mode 100644 reverb_models.h diff --git a/amp.cpp b/amp.cpp index b51927b..3b5730b 100644 --- a/amp.cpp +++ b/amp.cpp @@ -1,84 +1,83 @@ #include "amp.h" -#include "mustang.h" -#include "constants.h" +#include "magic.h" int -AmpCC::continuous_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = AMP_STATE; - cmd.parm2 = 0x02; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; - - return amp->continuous_control( cmd ); +AmpCC::continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x02; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; + + unsigned short magic = magic_values[value]; + cmd[9] = magic & 0xff; + cmd[10] = (magic >> 8) & 0xff; + return 0; } int -AmpCC::discrete_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = AMP_STATE; - cmd.parm2 = 0x02; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; +AmpCC::discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x02; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; - return amp->discrete_control( cmd ); + cmd[9] = value; + return 0; } int -AmpCC::dispatch( int cc, int value ) { +AmpCC::dispatch( int cc, int value, unsigned char *cmd ) { switch( cc ) { case 69: // Gain - return cc69( value ); + return cc69( value, cmd ); break; case 70: // Channel volume - return cc70( value ); + return cc70( value, cmd ); break; case 71: // Treble - return cc71( value ); + return cc71( value, cmd ); break; case 72: // Mid - return cc72( value ); + return cc72( value, cmd ); break; case 73: // Bass - return cc73( value ); + return cc73( value, cmd ); break; case 74: // Sag - return cc74( value ); + return cc74( value, cmd ); break; case 75: // Bias - return cc75( value ); + return cc75( value, cmd ); break; case 76: // Noise Gate - return cc76( value ); + return cc76( value, cmd ); break; case 77: // Cabinet - return cc77( value ); + return cc77( value, cmd ); break; case 78: // Presence / Gain2 / Cut - return cc78( value ); + return cc78( value, cmd ); break; case 79: // Blend / Master Volume - return cc79( value ); + return cc79( value, cmd ); break; default: - return 0; + return -1; break; } } diff --git a/amp.h b/amp.h index cfecdb4..e6c8f17 100644 --- a/amp.h +++ b/amp.h @@ -21,10 +21,8 @@ protected: unsigned char model[2]; unsigned char slot; - // Only base class is friend of Mustang, so forward calls from - // derived classes through these methods. - int continuous_control( int parm5, int parm6, int parm7, int value ); - int discrete_control( int parm5, int parm6, int parm7, int value ); + int continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); + int discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); public: AmpCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : @@ -34,50 +32,50 @@ public: memcpy( this->model, model, 2 ); } - int dispatch( int cc, int value ); + int dispatch( int cc, int value, unsigned char *cmd ); const unsigned char *getModel( void ) { return model;} const unsigned char getSlot( void ) { return slot;} private: // Gain - virtual int cc69( int value ) { return continuous_control( 0x01, 0x01, 0x0c, value );} + virtual int cc69( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x0c, value, cmd );} // Ch. Volume - virtual int cc70( int value ) { return continuous_control( 0x00, 0x00, 0x0c, value );} + virtual int cc70( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x0c, value, cmd );} // Treble - virtual int cc71( int value ) { return continuous_control( 0x04, 0x04, 0x0c, value );} + virtual int cc71( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x0c, value, cmd );} // Mid - virtual int cc72( int value ) { return continuous_control( 0x05, 0x05, 0x0c, value );} + virtual int cc72( int value, unsigned char *cmd ) { return continuous_control( 0x05, 0x05, 0x0c, value, cmd );} // Bass - virtual int cc73( int value ) { return continuous_control( 0x06, 0x06, 0x0c, value );} + virtual int cc73( int value, unsigned char *cmd ) { return continuous_control( 0x06, 0x06, 0x0c, value, cmd );} // Sag - virtual int cc74( int value ) { - if ( value > 2 ) return 0; - else return discrete_control( 0x13, 0x13, 0x8f, value ); + virtual int cc74( int value, unsigned char *cmd ) { + if ( value <= 2 ) return discrete_control( 0x13, 0x13, 0x8f, value, cmd ); + else return -1; } // Bias - virtual int cc75( int value ) { return continuous_control( 0x0a, 0x0a, 0x0d, value );} + virtual int cc75( int value, unsigned char *cmd ) { return continuous_control( 0x0a, 0x0a, 0x0d, value, cmd );} // Noise Gate - virtual int cc76( int value ) { - if ( value > 4 ) return 0; - else return discrete_control( 0x0f, 0x0f, 0x90, value ); + virtual int cc76( int value, unsigned char *cmd ) { + if ( value <= 4 ) return discrete_control( 0x0f, 0x0f, 0x90, value, cmd ); + else return -1; } // Cabinet - virtual int cc77( int value ) { - if ( value > 12 ) return 0; - else return discrete_control( 0x11, 0x11, 0x8e, value ); + virtual int cc77( int value, unsigned char *cmd ) { + if ( value <= 12 ) return discrete_control( 0x11, 0x11, 0x8e, value, cmd ); + else return -1; } // Dummy in base class - virtual int cc78( int value ) { return 0;} - virtual int cc79( int value ) { return 0;} + virtual int cc78( int value, unsigned char *cmd ) { return -1;} + virtual int cc79( int value, unsigned char *cmd ) { return -1;} // Noise Gate Custom Threshold - virtual int cc90( int value ) { - if ( value > 9 ) return 0; - else return discrete_control( 0x10, 0x10, 0x86, value ); + virtual int cc90( int value, unsigned char *cmd ) { + if ( value <= 9 ) return discrete_control( 0x10, 0x10, 0x86, value, cmd ); + else return -1; } // Noise Gate Custom Depth - virtual int cc91( int value ) { return continuous_control( 0x09, 0x09, 0x0c, value );} + virtual int cc91( int value, unsigned char *cmd ) { return continuous_control( 0x09, 0x09, 0x0c, value, cmd );} }; @@ -89,9 +87,9 @@ public: AmpCC1( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} private: // Presence - virtual int cc78( int value ) { return continuous_control( 0x07, 0x07, 0x0c, value );} + virtual int cc78( int value, unsigned char *cmd ) { return continuous_control( 0x07, 0x07, 0x0c, value, cmd );} // Blend - virtual int cc79( int value ) { return continuous_control( 0x02, 0x02, 0x0c, value );} + virtual int cc79( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x0c, value, cmd );} }; @@ -102,9 +100,9 @@ public: AmpCC2( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} private: // Gain2 - virtual int cc78( int value ) { return continuous_control( 0x02, 0x02, 0x0c, value );} + virtual int cc78( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x0c, value, cmd );} // Master Volume - virtual int cc79( int value ) { return continuous_control( 0x03, 0x03, 0x0c, value );} + virtual int cc79( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x0c, value, cmd );} }; @@ -115,9 +113,9 @@ public: AmpCC3( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} private: // Cut - virtual int cc78( int value ) { return continuous_control( 0x07, 0x07, 0x0c, value );} + virtual int cc78( int value, unsigned char *cmd ) { return continuous_control( 0x07, 0x07, 0x0c, value, cmd );} // Master Volume - virtual int cc79( int value ) { return continuous_control( 0x03, 0x03, 0x0c, value );} + virtual int cc79( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x0c, value, cmd );} }; @@ -131,9 +129,9 @@ public: AmpCC4( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} private: // Presence - virtual int cc78( int value ) { return continuous_control( 0x07, 0x07, 0x0c, value );} + virtual int cc78( int value, unsigned char *cmd ) { return continuous_control( 0x07, 0x07, 0x0c, value, cmd );} // Master Volume - virtual int cc79( int value ) { return continuous_control( 0x03, 0x03, 0x0c, value );} + virtual int cc79( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x0c, value, cmd );} }; @@ -144,11 +142,11 @@ public: AmpCC5( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} private: // No sag / bias - virtual int cc74( int value ) { return 0;} - virtual int cc75( int value ) { return 0;} + virtual int cc74( int value, unsigned char *cmd ) { return -1;} + virtual int cc75( int value, unsigned char *cmd ) { return -1;} // No pres / master - virtual int cc78( int value ) { return 0;} - virtual int cc79( int value ) { return 0;} + virtual int cc78( int value, unsigned char *cmd ) { return -1;} + virtual int cc79( int value, unsigned char *cmd ) { return -1;} }; @@ -156,10 +154,10 @@ private: // class AmpCC6 : public AmpCC { public: - AmpCC6( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} + AmpCC6( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {;} private: // Master Volume - virtual int cc79( int value ) { return continuous_control( 0x03, 0x03, 0x0c, value );} + virtual int cc79( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x0c, value, cmd );} }; @@ -170,7 +168,7 @@ public: AmpCC7( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} private: // Presence - virtual int cc78( int value ) { return continuous_control( 0x07, 0x07, 0x0c, value );} + virtual int cc78( int value, unsigned char *cmd ) { return continuous_control( 0x07, 0x07, 0x0c, value, cmd );} }; @@ -180,17 +178,17 @@ class NullAmpCC : public AmpCC { public: NullAmpCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : AmpCC(theAmp,model,theSlot) {} private: - virtual int cc69( int value ) { return 0;} - virtual int cc70( int value ) { return 0;} - virtual int cc71( int value ) { return 0;} - virtual int cc72( int value ) { return 0;} - virtual int cc73( int value ) { return 0;} - virtual int cc74( int value ) { return 0;} - virtual int cc75( int value ) { return 0;} - virtual int cc76( int value ) { return 0;} - virtual int cc77( int value ) { return 0;} - virtual int cc78( int value ) { return 0;} - virtual int cc79( int value ) { return 0;} + virtual int cc69( int value, unsigned char *cmd ) { return -1;} + virtual int cc70( int value, unsigned char *cmd ) { return -1;} + virtual int cc71( int value, unsigned char *cmd ) { return -1;} + virtual int cc72( int value, unsigned char *cmd ) { return -1;} + virtual int cc73( int value, unsigned char *cmd ) { return -1;} + virtual int cc74( int value, unsigned char *cmd ) { return -1;} + virtual int cc75( int value, unsigned char *cmd ) { return -1;} + virtual int cc76( int value, unsigned char *cmd ) { return -1;} + virtual int cc77( int value, unsigned char *cmd ) { return -1;} + virtual int cc78( int value, unsigned char *cmd ) { return -1;} + virtual int cc79( int value, unsigned char *cmd ) { return -1;} }; #endif diff --git a/amp_models.cpp b/amp_models.cpp index 6ebfc3a..58b4a32 100644 --- a/amp_models.cpp +++ b/amp_models.cpp @@ -1,5 +1,7 @@ #include "amp_models.h" +const unsigned char null_amp_id[] = { 0x00, 0x00 }; + const unsigned char f57_deluxe_id[] = { 0x67, 0x00 }; const unsigned char f59_bassman_id[] = { 0x64, 0x00 }; const unsigned char f57_champ_id[] = { 0x7c, 0x00 }; diff --git a/amp_models.h b/amp_models.h index ecfd3c1..d5635a7 100644 --- a/amp_models.h +++ b/amp_models.h @@ -1,6 +1,8 @@ #ifndef AMP_MODELS_H #define AMP_MODELS_H +extern const unsigned char null_amp_id[]; + extern const unsigned char f57_deluxe_id[]; extern const unsigned char f59_bassman_id[]; extern const unsigned char f57_champ_id[]; diff --git a/constants.h b/constants.h index 53b384b..e927eb2 100644 --- a/constants.h +++ b/constants.h @@ -13,18 +13,10 @@ #define MI_II_V2 0x0014 #define MIII_IV_V_V2 0x0016 -#define DSP 2 -#define PATCH_SLOT 4 -#define EFFECT 16 #define FXSLOT 18 -// direct control fields -#define FAMILY 2 -#define ACTIVE_INVERT 3 - // Offset to current device model for any state structure #define MODEL 16 -#define MODELX 17 // Index into current state structure #define AMP_STATE 0 @@ -34,19 +26,6 @@ #define REVERB_STATE 4 #define PEDAL_STATE 5 -// DSP Category -#define AMP_DSP 5 -#define STOMP_DSP 6 -#define MOD_DSP 7 -#define DELAY_DSP 8 -#define REVERB_DSP 9 - -// DSP Family (used for direct parm set) - Effectively DSP - 3 -#define STOMP_FAM 3 -#define MOD_FAM 4 -#define DELAY_FAM 5 -#define REVERB_FAM 6 - // Reverb model id values #define SM_HALL_ID 0x0024 #define LG_HALL_ID 0x003a diff --git a/delay.cpp b/delay.cpp index 60f99e4..f6b2a78 100644 --- a/delay.cpp +++ b/delay.cpp @@ -1,62 +1,61 @@ #include "delay.h" -#include "mustang.h" -#include "constants.h" +#include "magic.h" int -DelayCC::continuous_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = DELAY_STATE; - cmd.parm2 = 0x05; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; - - return amp->continuous_control( cmd ); +DelayCC::continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x05; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; + + unsigned short magic = magic_values[value]; + cmd[9] = magic & 0xff; + cmd[10] = (magic >> 8) & 0xff; + return 0; } int -DelayCC::discrete_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = DELAY_STATE; - cmd.parm2 = 0x05; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; +DelayCC::discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x05; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; - return amp->discrete_control( cmd ); + cmd[9] = value; + return 0; } int -DelayCC::dispatch( int cc, int value ) { +DelayCC::dispatch( int cc, int value, unsigned char *cmd ) { switch ( cc ) { case 49: // Level - return cc49( value ); + return cc49( value, cmd ); break; case 50: // Delay Time - return cc50( value ); + return cc50( value, cmd ); break; case 51: // Feedback / FFdbk - return cc51( value ); + return cc51( value, cmd ); break; case 52: // Brightness / Frequency / Release / RFdbk / Flutter - return cc52( value ); + return cc52( value, cmd ); break; case 53: // Attenuation / Resonance / Mode / Stereo / Threshold // Tone / Brightness / Separation - return cc53( value ); + return cc53( value, cmd ); break; case 54: // Input Level / Stereo / Brightness - return cc54( value ); + return cc54( value, cmd ); break; default: return 0; diff --git a/delay.h b/delay.h index 9ea57e6..08937d6 100644 --- a/delay.h +++ b/delay.h @@ -14,8 +14,8 @@ protected: unsigned char model[2]; unsigned char slot; - int continuous_control( int parm5, int parm6, int parm7, int value ); - int discrete_control( int parm5, int parm6, int parm7, int value ); + int continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); + int discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); public: DelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : @@ -25,20 +25,20 @@ public: memcpy( this->model, model, 2 ); } - int dispatch( int cc, int value ); + int dispatch( int cc, int value, unsigned char *cmd ); const unsigned char *getModel( void ) { return model;} const unsigned char getSlot( void ) { return slot;} private: // Level - virtual int cc49( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc49( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Delay Time - virtual int cc50( int value ) { return continuous_control( 0x01, 0x01, 0x06, value );} + virtual int cc50( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x06, value, cmd );} - virtual int cc51( int value ) = 0; - virtual int cc52( int value ) = 0; - virtual int cc53( int value ) = 0; - virtual int cc54( int value ) = 0; + virtual int cc51( int value, unsigned char *cmd ) = 0; + virtual int cc52( int value, unsigned char *cmd ) = 0; + virtual int cc53( int value, unsigned char *cmd ) = 0; + virtual int cc54( int value, unsigned char *cmd ) = 0; }; @@ -47,13 +47,13 @@ public: MonoDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // Feedback - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Brightness - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Attenuation - virtual int cc53( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc53( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} // no-op - virtual int cc54( int value ) { return 0;} + virtual int cc54( int value, unsigned char *cmd ) { return -1;} }; @@ -62,13 +62,13 @@ public: EchoFilterCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // Feedback - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Frequency - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Resonance - virtual int cc53( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc53( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} // Input Level - virtual int cc54( int value ) { return continuous_control( 0x05, 0x05, 0x01, value );} + virtual int cc54( int value, unsigned char *cmd ) { return continuous_control( 0x05, 0x05, 0x01, value, cmd );} }; @@ -77,18 +77,18 @@ public: MultitapDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // Delay Time - virtual int cc50( int value ) { return continuous_control( 0x01, 0x01, 0x08, value );} + virtual int cc50( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x08, value, cmd );} // Feedback - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Brightness - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Mode - virtual int cc53( int value ) { - if ( value > 3 ) return 0; - else return discrete_control( 0x04, 0x04, 0x8b, value ); + virtual int cc53( int value, unsigned char *cmd ) { + if ( value > 3 ) return -1; + else return discrete_control( 0x04, 0x04, 0x8b, value, cmd ); } // no-op - virtual int cc54( int value ) { return 0;} + virtual int cc54( int value, unsigned char *cmd ) { return -1;} }; @@ -97,13 +97,13 @@ public: PingPongDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // Feedback - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Brightness - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Stereo - virtual int cc53( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc53( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} // no-op - virtual int cc54( int value ) { return 0;} + virtual int cc54( int value, unsigned char *cmd ) { return -1;} }; @@ -112,13 +112,13 @@ public: DuckingDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // Feedback - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Release - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Threshold - virtual int cc53( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc53( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} // no-op - virtual int cc54( int value ) { return 0;} + virtual int cc54( int value, unsigned char *cmd ) { return -1;} }; @@ -127,13 +127,13 @@ public: ReverseDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // FFdbk - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // RFdbk - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Tone - virtual int cc53( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc53( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} // no-op - virtual int cc54( int value ) { return 0;} + virtual int cc54( int value, unsigned char *cmd ) { return -1;} }; @@ -142,13 +142,13 @@ public: TapeDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // Feedback - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Flutter - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Brightness - virtual int cc53( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc53( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} // Stereo - virtual int cc54( int value ) { return continuous_control( 0x05, 0x05, 0x01, value );} + virtual int cc54( int value, unsigned char *cmd ) { return continuous_control( 0x05, 0x05, 0x01, value, cmd );} }; @@ -157,13 +157,13 @@ public: StereoTapeDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: // Feedback - virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc51( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Flutter - virtual int cc52( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc52( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Separation - virtual int cc53( int value ) { return continuous_control( 0x04, 0x05, 0x01, value );} + virtual int cc53( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x05, 0x01, value, cmd );} // Brightness - virtual int cc54( int value ) { return continuous_control( 0x05, 0x04, 0x01, value );} + virtual int cc54( int value, unsigned char *cmd ) { return continuous_control( 0x05, 0x04, 0x01, value, cmd );} }; @@ -171,12 +171,12 @@ class NullDelayCC : public DelayCC { public: NullDelayCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : DelayCC(theAmp,model,theSlot) {} private: - virtual int cc49( int value ) { return 0;} - virtual int cc50( int value ) { return 0;} - virtual int cc51( int value ) { return 0;} - virtual int cc52( int value ) { return 0;} - virtual int cc53( int value ) { return 0;} - virtual int cc54( int value ) { return 0;} + virtual int cc49( int value, unsigned char *cmd ) { return -1;} + virtual int cc50( int value, unsigned char *cmd ) { return -1;} + virtual int cc51( int value, unsigned char *cmd ) { return -1;} + virtual int cc52( int value, unsigned char *cmd ) { return -1;} + virtual int cc53( int value, unsigned char *cmd ) { return -1;} + virtual int cc54( int value, unsigned char *cmd ) { return -1;} }; diff --git a/delay_models.cpp b/delay_models.cpp index ef6ae4b..fffcd84 100644 --- a/delay_models.cpp +++ b/delay_models.cpp @@ -1,5 +1,7 @@ #include "delay_models.h" +const unsigned char null_dly_id[] = { 0x00, 0x00 }; + const unsigned char mono_dly_id[] = { 0x16, 0x00 }; const unsigned char mono_filter_id[] = { 0x43, 0x00 }; const unsigned char st_filter_id[] = { 0x48, 0x00 }; diff --git a/delay_models.h b/delay_models.h index bbfa0e5..b1ae1e4 100644 --- a/delay_models.h +++ b/delay_models.h @@ -1,6 +1,8 @@ #ifndef DELAY_MODELS_H #define DELAY_MODELS_H +extern const unsigned char null_dly_id[]; + extern const unsigned char mono_dly_id[]; extern const unsigned char mono_filter_id[]; extern const unsigned char st_filter_id[]; diff --git a/magic.cpp b/magic.cpp new file mode 100644 index 0000000..d3e5f45 --- /dev/null +++ b/magic.cpp @@ -0,0 +1,25 @@ +// Magic values for direct conditioning of Mustang analog controls +// + +#include "magic.h" + +unsigned short magic_values[] = { + 0x0000, 0x01e1, 0x036a, 0x04f3, 0x067c, 0x085d, 0x0a69, 0x0fdf, + 0x100b, 0x129a, 0x1555, 0x178d, 0x199a, 0x1af7, 0x1c80, 0x1fbe, + 0x2016, 0x21cb, 0x2354, 0x2486, 0x263b, 0x2873, 0x29fc, 0x2f9e, + 0x30a4, 0x3333, 0x3514, 0x36f4, 0x3826, 0x39db, 0x3b64, 0x3fd4, + 0x402b, 0x41e0, 0x43ed, 0x45f9, 0x47ae, 0x490b, 0x4ac0, 0x4f88, + 0x500b, 0x5217, 0x547b, 0x5604, 0x57e4, 0x5999, 0x5ba6, 0x5fea, + 0x6041, 0x6279, 0x642e, 0x6692, 0x6872, 0x6a53, 0x6c33, 0x6ff5, + 0x7020, 0x7201, 0x7439, 0x7619, 0x7851, 0x79af, 0x7b90, 0x7fff, + 0x8083, 0x8237, 0x8418, 0x8624, 0x8805, 0x898e, 0x8b9a, 0x8f87, + 0x900a, 0x926e, 0x947a, 0x96de, 0x9893, 0x9a1c, 0x9b4e, 0x9f92, + 0xa041, 0xa24d, 0xa42e, 0xa5e3, 0xa7ef, 0xa9d0, 0xab59, 0xaf9d, + 0xb020, 0xb201, 0xb38a, 0xb56a, 0xb74b, 0xb957, 0xbb38, 0xbfff, + 0xc057, 0xc28f, 0xc51e, 0xc72a, 0xc888, 0xca68, 0xcc75, 0xcfb3, + 0xd00a, 0xd168, 0xd2f1, 0xd4a6, 0xd686, 0xd8be, 0xdacb, 0xdfe9, + 0xe041, 0xe221, 0xe3d6, 0xe5e2, 0xe7ef, 0xe978, 0xeb84, 0xeff4, + 0xf077, 0xf40d, 0xf56a, 0xf74b, 0xf9da, 0xfbe6, 0xfe4a, 0xffff +}; + + diff --git a/magic.h b/magic.h index c922063..569c0c1 100644 --- a/magic.h +++ b/magic.h @@ -4,35 +4,6 @@ #ifndef _MAGIC_H #define _MAGIC_H -unsigned short magic_values[] = { - 0x0000, 0x013b, 0x02ef, 0x036a, 0x04a4, 0x0659, 0x06d4, 0x080e, 0x0a3d, 0x0b78, - 0x0bf2, 0x0d2d, 0x0da7, 0x0ee2, 0x0f5c, 0x1111, 0x124c, 0x12c6, 0x1400, 0x147b, - 0x1630, 0x176a, 0x17e5, 0x191f, 0x1999, 0x1ad4, 0x1b4e, 0x1c89, 0x1d03, 0x1e3e, - 0x1eb8, 0x1ff3, 0x206d, 0x21a8, 0x2222, 0x235d, 0x23d7, 0x2511, 0x258c, 0x26c6, - 0x2741, 0x287b, 0x28f6, 0x2a30, 0x2aaa, 0x2be5, 0x2c5f, 0x2d9a, 0x2e14, 0x2f4f, - 0x2fc9, 0x3104, 0x317e, 0x32b9, 0x3333, 0x346e, 0x34e8, 0x3622, 0x369d, 0x37d7, - 0x3852, 0x398c, 0x3a07, 0x3b41, 0x3bbb, 0x3cf6, 0x3d70, 0x3eab, 0x3f25, 0x4060, - 0x40da, 0x4215, 0x428f, 0x43ca, 0x4444, 0x457f, 0x45f9, 0x4733, 0x47ae, 0x48e8, - 0x4963, 0x4a9d, 0x4b18, 0x4c52, 0x4ccc, 0x4e07, 0x4e81, 0x4fbc, 0x5036, 0x5171, - 0x51eb, 0x5326, 0x53a0, 0x54db, 0x5555, 0x5690, 0x570a, 0x5844, 0x58bf, 0x59f9, - 0x5a74, 0x5bae, 0x5c29, 0x5d63, 0x5dde, 0x5f18, 0x5f92, 0x60cd, 0x6282, 0x62fc, - 0x6437, 0x64b1, 0x65ec, 0x6666, 0x67a1, 0x681b, 0x6955, 0x69d0, 0x6b0a, 0x6b85, - 0x6cbf, 0x6d3a, 0x6e74, 0x6eef, 0x7029, 0x70a3, 0x71de, 0x7258, 0x7393, 0x740d, - 0x7548, 0x75c2, 0x76fd, 0x7777, 0x78b2, 0x792c, 0x7a66, 0x7ae1, 0x7c1b, 0x7c96, - 0x7dd0, 0x7e4b, 0x7f85, 0x8000, 0x813a, 0x81b4, 0x82ef, 0x8369, 0x84a4, 0x851e, - 0x8659, 0x86d3, 0x880e, 0x8888, 0x89c3, 0x8a3d, 0x8bf2, 0x8d2c, 0x8da7, 0x8ee1, - 0x9096, 0x9111, 0x924b, 0x92c5, 0x947a, 0x962f, 0x97e4, 0x9b4e, 0x9d03, 0x9eb8, - 0xa06d, 0xa222, 0xa3d6, 0xa58b, 0xa740, 0xa8f5, 0xaaaa, 0xac5f, 0xafc9, 0xb17e, - 0xb333, 0xb4e7, 0xb851, 0xba06, 0xbbbb, 0xbd70, 0xbf25, 0xc0da, 0xc28f, 0xc444, - 0xc5f8, 0xc962, 0xcb17, 0xcccc, 0xce81, 0xd036, 0xd1eb, 0xd3a0, 0xd555, 0xd709, - 0xd8be, 0xda73, 0xdc28, 0xdddd, 0xdf92, 0xe147, 0xe2fc, 0xe4b1, 0xe666, 0xe81a, - 0xe9cf, 0xeb84, 0xf0a3, 0xf258, 0xf5c2, 0xf92b, 0xfae0, 0xfe4a, 0xffff -}; - -// Max index in array -unsigned magic_max = 218; - -// Scale MIDI CC value to array index -double magic_scale_factor = 1.711; +extern unsigned short magic_values[]; #endif diff --git a/mod.cpp b/mod.cpp index 300e722..583d425 100644 --- a/mod.cpp +++ b/mod.cpp @@ -1,57 +1,56 @@ #include "mod.h" -#include "mustang.h" -#include "constants.h" +#include "magic.h" int -ModCC::continuous_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = MOD_STATE; - cmd.parm2 = 0x04; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; - - return amp->continuous_control( cmd ); +ModCC::continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x04; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; + + unsigned short magic = magic_values[value]; + cmd[9] = magic & 0xff; + cmd[10] = (magic >> 8) & 0xff; + return 0; } int -ModCC::discrete_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = MOD_STATE; - cmd.parm2 = 0x04; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; +ModCC::discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x04; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; - return amp->discrete_control( cmd ); + cmd[9] = value; + return 0; } int -ModCC::dispatch( int cc, int value ) { +ModCC::dispatch( int cc, int value, unsigned char *cmd ) { switch ( cc ) { case 39: // Level / Mix - return cc39( value ); + return cc39( value, cmd ); break; case 40: // Rate / Rotor / Freq / Pitch - return cc40( value ); + return cc40( value, cmd ); break; case 41: // Depth / Duty Cycle / Resonance / Detune / Heel Freq - return cc41( value ); + return cc41( value, cmd ); break; case 42: // Delay / Fdbk / LFO / Min Freq / Feedback / Toe Freq - return cc42( value ); + return cc42( value, cmd ); break; case 43: // LR Phase / Release / Tri Shape / PreDelay / High Q - return cc43( value ); + return cc43( value, cmd ); break; default: return 0; diff --git a/mod.h b/mod.h index ea67298..23646f4 100644 --- a/mod.h +++ b/mod.h @@ -14,8 +14,8 @@ protected: unsigned char model[2]; unsigned char slot; - int continuous_control( int parm5, int parm6, int parm7, int value ); - int discrete_control( int parm5, int parm6, int parm7, int value ); + int continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); + int discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); public: ModCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : @@ -25,16 +25,16 @@ public: memcpy( this->model, model, 2 ); } - int dispatch( int cc, int value ); + int dispatch( int cc, int value, unsigned char *cmd ); const unsigned char *getModel( void ) { return model;} const unsigned char getSlot( void ) { return slot;} private: - virtual int cc39( int value ) = 0; - virtual int cc40( int value ) = 0; - virtual int cc41( int value ) = 0; - virtual int cc42( int value ) = 0; - virtual int cc43( int value ) = 0; + virtual int cc39( int value, unsigned char *cmd ) = 0; + virtual int cc40( int value, unsigned char *cmd ) = 0; + virtual int cc41( int value, unsigned char *cmd ) = 0; + virtual int cc42( int value, unsigned char *cmd ) = 0; + virtual int cc43( int value, unsigned char *cmd ) = 0; }; @@ -43,15 +43,15 @@ public: ChorusCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Rate - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x10, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x10, value, cmd );} // Depth - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Avg Delay - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // LR Phase - virtual int cc43( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -60,15 +60,15 @@ public: FlangerCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Rate - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x10, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x10, value, cmd );} // Depth - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Feedback - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // LR Phase - virtual int cc43( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -77,15 +77,15 @@ public: VibratoneCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Rotor Speed - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x0f, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x0f, value, cmd );} // Depth - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Feedback - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // LR Phase - virtual int cc43( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -94,15 +94,15 @@ public: TremCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Rotor Speed - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x0e, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x0e, value, cmd );} // Duty Cycle - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Attack / LFO Clip - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Release / Tri Shape - virtual int cc43( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -111,18 +111,18 @@ public: RingModCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Freq - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Depth - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // LFO Depth - virtual int cc42( int value ) { - if ( value > 1 ) return 0; - else return discrete_control( 0x03, 0x03, 0x8c, value ); + virtual int cc42( int value, unsigned char *cmd ) { + if ( value > 1 ) return -1; + else return discrete_control( 0x03, 0x03, 0x8c, value, cmd ); } // LFO Phase - virtual int cc43( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -131,15 +131,15 @@ public: StepFilterCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Rate - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x10, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x10, value, cmd );} // Resonance - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Min Freq - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Max Freq - virtual int cc43( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -148,17 +148,17 @@ public: PhaserCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Rate - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x10, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x10, value, cmd );} // Depth - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Feedback - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // LFO Shape - virtual int cc43( int value ) { - if ( value > 1 ) return 0; - else return discrete_control( 0x04, 0x04, 0x8c, value ); + virtual int cc43( int value, unsigned char *cmd ) { + if ( value > 1 ) return -1; + else return discrete_control( 0x04, 0x04, 0x8c, value, cmd ); } }; @@ -168,15 +168,15 @@ public: PitchShifterCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Level - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Pitch - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Detune - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Feedback - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Predelay - virtual int cc43( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; // Wah + Touch Wah @@ -185,17 +185,17 @@ public: ModWahCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Mix - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Freq - virtual int cc40( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc40( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Heel Freq - virtual int cc41( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc41( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Toe Freq - virtual int cc42( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc42( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Hi-Q - virtual int cc43( int value ) { - if ( value > 1 ) return 0; - else return discrete_control( 0x04, 0x04, 0x81, value ); + virtual int cc43( int value, unsigned char *cmd ) { + if ( value > 1 ) return -1; + else return discrete_control( 0x04, 0x04, 0x81, value, cmd ); } }; @@ -205,24 +205,24 @@ public: DiatonicShiftCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: // Mix - virtual int cc39( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc39( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Pitch - virtual int cc40( int value ) { - if ( value > 0x15 ) return 0; - else return discrete_control( 0x01, 0x0b, 0x98, value ); + virtual int cc40( int value, unsigned char *cmd ) { + if ( value > 0x15 ) return -1; + else return discrete_control( 0x01, 0x0b, 0x98, value, cmd ); } // Key - virtual int cc41( int value ) { - if ( value > 0x0b ) return 0; - else return discrete_control( 0x02, 0x02, 0x99, value ); + virtual int cc41( int value, unsigned char *cmd ) { + if ( value > 0x0b ) return -1; + else return discrete_control( 0x02, 0x02, 0x99, value, cmd ); } // Scale - virtual int cc42( int value ) { - if ( value > 8 ) return 0; - else return discrete_control( 0x03, 0x03, 0x9a, value ); + virtual int cc42( int value, unsigned char *cmd ) { + if ( value > 8 ) return -1; + else return discrete_control( 0x03, 0x03, 0x9a, value, cmd ); } // Tone - virtual int cc43( int value ) { return continuous_control( 0x04, 0x07, 0x01, value );} + virtual int cc43( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x07, 0x01, value, cmd );} }; @@ -230,11 +230,11 @@ class NullModCC : public ModCC { public: NullModCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ModCC(theAmp,model,theSlot) {} private: - virtual int cc39( int value ) { return 0;} - virtual int cc40( int value ) { return 0;} - virtual int cc41( int value ) { return 0;} - virtual int cc42( int value ) { return 0;} - virtual int cc43( int value ) { return 0;} + virtual int cc39( int value, unsigned char *cmd ) { return -1;} + virtual int cc40( int value, unsigned char *cmd ) { return -1;} + virtual int cc41( int value, unsigned char *cmd ) { return -1;} + virtual int cc42( int value, unsigned char *cmd ) { return -1;} + virtual int cc43( int value, unsigned char *cmd ) { return -1;} }; diff --git a/mod_models.cpp b/mod_models.cpp index 949802a..7e53cef 100644 --- a/mod_models.cpp +++ b/mod_models.cpp @@ -1,5 +1,7 @@ #include "mod_models.h" +const unsigned char null_mod_id[] = { 0x00, 0x00 }; + const unsigned char sine_chorus_id[] = { 0x12, 0x00 }; const unsigned char tri_chorus_id[] = { 0x13, 0x00 }; const unsigned char sine_flange_id[] = { 0x18, 0x00 }; diff --git a/mod_models.h b/mod_models.h index 2c8f45c..53cf9c0 100644 --- a/mod_models.h +++ b/mod_models.h @@ -3,6 +3,8 @@ #ifndef MOD_MODELS_H #define MOD_MODELS_H +extern const unsigned char null_mod_id[]; + extern const unsigned char sine_chorus_id[]; extern const unsigned char tri_chorus_id[]; extern const unsigned char sine_flange_id[]; diff --git a/mustang.cpp b/mustang.cpp index 24f8637..b3b0ed9 100644 --- a/mustang.cpp +++ b/mustang.cpp @@ -1,7 +1,7 @@ #include "mustang.h" #include - +#include #include #include "magic.h" @@ -22,12 +22,13 @@ #include "stomp_models.h" #include "mod_models.h" #include "delay_models.h" +#include "reverb_models.h" // Parameter report (preset names + DSP states) const unsigned char Mustang::state_prefix[] = { 0x1c, 0x01 }; // End of full parameter dump -const unsigned char Mustang::parms_done[] = { 0xff, 0x01 }; +const unsigned char Mustang::parm_read_ack[] = { 0xff, 0x01 }; // Acknowledge tuner toggle const unsigned char Mustang::tuner_ack[] = { 0x0a, 0x01 }; @@ -36,7 +37,10 @@ const unsigned char Mustang::tuner_ack[] = { 0x0a, 0x01 }; const unsigned char Mustang::tuner_prefix[] = { 0x0b, 0x01 }; // Acknowledge model-select -const unsigned char Mustang::select_ack[] = { 0x00, 0x00, 0x1c }; +const unsigned char Mustang::model_change_ack[] = { 0x00, 0x00, 0x1c }; + +// Acknowledge EFX toggle +const unsigned char Mustang::efx_toggle_ack[] = { 0x00, 0x00, 0x19 }; // Acknowledge CC const unsigned char Mustang::cc_ack[] = { 0x00, 0x00, 0x05 }; @@ -59,6 +63,8 @@ Mustang::Mustang( void ) { memset( execute, 0x00, 64 ); execute[0] = 0x1c; execute[1] = 0x03; + + tuner_active = false; } @@ -97,7 +103,7 @@ Mustang::handleInput( void ) { if ( total_count!=64 ) continue; total_count = 0; -#if 0 +#ifdef DEBUG for ( int i=0; i<64; i++ ) fprintf( stderr, "%02x ", read_buf[i] ); fprintf( stderr, "\n" ); #endif @@ -106,6 +112,16 @@ Mustang::handleInput( void ) { // Only care about amp state messages, and not even all of them... int dsp_category = read_buf[2]; switch( dsp_category ) { + case 0x00: + { + // Patch change report done + pthread_mutex_lock( &cc_ack_eom.lock ); + + cc_ack_eom.value = true; + pthread_cond_signal( &cc_ack_eom.cond ); + pthread_mutex_unlock( &cc_ack_eom.lock ); + break; + } case 0x04: { // Preset name @@ -213,7 +229,31 @@ Mustang::handleInput( void ) { break; } } - else if ( 0==memcmp(read_buf,parms_done,2) ){ + else if ( 0==memcmp(read_buf,model_change_ack,3) ) { + // Received acknowledge of model change + pthread_mutex_lock( &model_change_sync.lock ); + + model_change_sync.value = true; + pthread_cond_signal( &model_change_sync.cond ); + pthread_mutex_unlock( &model_change_sync.lock ); + } + else if ( 0==memcmp(read_buf,cc_ack,3) ){ + // CC command acknowledged + pthread_mutex_lock( &cc_ack_sync.lock ); + + cc_ack_sync.value = true; + pthread_cond_signal( &cc_ack_sync.cond ); + pthread_mutex_unlock( &cc_ack_sync.lock ); + } + else if ( 0==memcmp(read_buf,efx_toggle_ack,3) ){ + // EFX Toggle acknowledged + pthread_mutex_lock( &efx_toggle_sync.lock ); + + efx_toggle_sync.value = true; + pthread_cond_signal( &efx_toggle_sync.cond ); + pthread_mutex_unlock( &efx_toggle_sync.lock ); + } + else if ( 0==memcmp(read_buf,parm_read_ack,2) ){ // Parameter dump complete, notify main thread pthread_mutex_lock( &parm_read_sync.lock ); @@ -221,6 +261,14 @@ Mustang::handleInput( void ) { pthread_cond_signal( &parm_read_sync.cond ); pthread_mutex_unlock( &parm_read_sync.lock ); } + else if ( 0==memcmp(read_buf,tuner_ack,2) ){ + // Parameter dump complete, notify main thread + pthread_mutex_lock( &tuner_ack_sync.lock ); + + tuner_ack_sync.value = true; + pthread_cond_signal( &tuner_ack_sync.cond ); + pthread_mutex_unlock( &tuner_ack_sync.lock ); + } } long result = rc; @@ -228,6 +276,29 @@ Mustang::handleInput( void ) { } +int +Mustang::sendCmd( unsigned char *buffer ) { + int total_count = 0; + int attempts = 5; + + while ( total_count < 64 ) { + int count; + int rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); + if ( rc ) { + if ( rc==LIBUSB_ERROR_TIMEOUT ) { + // Up to five retries on timeout + if ( attempts==0 ) return rc; + else attempts--; + } + // All other errors immediately fatal + else return rc; + } + total_count += count; + } + return 0; +} + + int Mustang::initialize( void ) { int rc; @@ -256,11 +327,11 @@ Mustang::initialize( void ) { // If kernel driver is active, detach it if ( libusb_kernel_driver_active( usb_io,0) ) { // If detach fails, we're hosed... - if ( 0 != (rc = libusb_detach_kernel_driver( usb_io,0)) ) return rc; + if ( 0 != (rc = libusb_detach_kernel_driver(usb_io,0)) ) return rc; } // Make it ours - if ( 0 != (rc = libusb_claim_interface( usb_io,0)) ) return rc; + if ( 0 != (rc = libusb_claim_interface(usb_io,0)) ) return rc; unsigned char buffer[64]; int total_count; @@ -269,14 +340,9 @@ Mustang::initialize( void ) { memset( buffer, 0, 64 ); buffer[1] = 0xc3; - total_count = 0; - while ( total_count < 64 ) { - int count; - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - if ( rc && rc!=LIBUSB_ERROR_TIMEOUT ) return rc; - total_count += count; - } - + rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; + // Clear reply total_count = 0; while ( total_count < 64 ) { @@ -291,13 +357,8 @@ Mustang::initialize( void ) { buffer[0] = 0x1a; buffer[1] = init_value; - total_count = 0; - while ( total_count < 64 ) { - int count; - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - if ( rc && rc!=LIBUSB_ERROR_TIMEOUT ) return rc; - total_count += count; - } + rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; // Clear reply total_count = 0; @@ -323,7 +384,7 @@ Mustang::commStart( void ) { // Lock the flag pthread_mutex_lock( &parm_read_sync.lock ); parm_read_sync.value = false; - + // Start thread pthread_create( &worker, NULL, threadStarter, this ); @@ -331,14 +392,9 @@ Mustang::commStart( void ) { memset( buffer, 0, 64 ); buffer[0] = 0xff; buffer[1] = 0xc1; - int total_count = 0; - - while ( total_count < 64 ) { - int count; - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - if ( rc && rc!=LIBUSB_ERROR_TIMEOUT ) return rc; - total_count += count; - } + + rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; // Block until background thread tells us it's done while ( !parm_read_sync.value ) pthread_cond_wait( &parm_read_sync.cond, &parm_read_sync.lock ); @@ -379,30 +435,102 @@ Mustang::deinitialize( void ) { } -int -Mustang::tunerMode( int value ) { - int rc, count; +int +Mustang::requestDump( void ) { + int rc; unsigned char buffer[64]; - memset(buffer, 0x00, 64); - buffer[0] = 0x0a; - buffer[1] = 0x01; + // Lock the flag + pthread_mutex_lock( &parm_read_sync.lock ); + parm_read_sync.value = false; + + // Request parm dump + memset( buffer, 0, 64 ); + buffer[0] = 0xff; + buffer[1] = 0xc1; - if ( value > 63 && value <= 127 ) { - // Tuner on - buffer[2] = buffer[3] = buffer[4] = 0x01; - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); + rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; - tuner_active = true; + // Block until background thread tells us it's done + while ( !parm_read_sync.value ) pthread_cond_wait( &parm_read_sync.cond, &parm_read_sync.lock ); + pthread_mutex_unlock( &parm_read_sync.lock ); + +#ifdef DEBUG + fprintf( stderr, "DEBUG: Parm dump completion acknowledged\n" ); +#endif + + return 0; +} + + +int +Mustang::executeModelChange( unsigned char *buffer ) { + // 5..9 --> 0..4 + int idx = buffer[2] - 5; + + /////// CRITICAL + // + pthread_mutex_lock( &model_change_sync.lock ); + + // Setup amp personality + model_change_sync.value = false; + + int rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; + + // Sync on resonse + while ( !model_change_sync.value ) pthread_cond_wait( &model_change_sync.cond, &model_change_sync.lock ); + + // Execute command + model_change_sync.value = false; + + rc = sendCmd( execute ); + if ( rc!=0 ) return rc; + + while ( !model_change_sync.value ) pthread_cond_wait( &model_change_sync.cond, &model_change_sync.lock ); + pthread_mutex_unlock( &model_change_sync.lock ); + // + ////// + +#ifdef DEBUG + fprintf( stderr, "DEBUG: Model change acknowledged\n" ); +#endif + + // Lock the DSP device and update for what we just sent + pthread_mutex_lock( &dsp_sync[idx].lock ); + + // Update DSP state buffer + memcpy( dsp_parms[idx], (const char *)buffer, 64 ); + unsigned char *curr = dsp_parms[idx]; + + // Make it look like a status report: + curr[1] = 0x03; + curr[4] = 0x00; + curr[7] = 0x01; + + switch ( idx ) { + case 0: + updateAmpObj( curr ); + break; + case 1: + updateStompObj( curr ); + break; + case 2: + updateModObj( curr ); + break; + case 3: + updateDelayObj( curr ); + break; + case 4: + updateReverbObj( curr ); + break; } - else if ( value >= 0 && value <= 63 ) { - // Tuner off - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); + pthread_mutex_unlock( &dsp_sync[idx].lock ); - libusb_interrupt_transfer( usb_io, USB_IN, buffer, 64, &count, USB_TIMEOUT_MS ); - // sleep( 1 ); - tuner_active = false; - } +#ifdef DEBUG + fprintf( stderr, "DEBUG: State updated\n" ); +#endif return rc; } @@ -414,7 +542,7 @@ Mustang::updateAmpObj( const unsigned char *data ) { AmpCC * new_amp = NULL; const unsigned char *model = data + MODEL; - + if ( is_type(f57_deluxe_id,model) || is_type(f57_champ_id,model) || is_type(f65_deluxe_id,model) || @@ -448,6 +576,9 @@ Mustang::updateAmpObj( const unsigned char *data ) { else if ( is_type(f57_twin_id,model) ) { new_amp = new AmpCC7( this, model, 0 ); } + else if ( is_type(null_amp_id,model) ) { + new_amp = new NullAmpCC( this, model, 0 ); + } else { fprintf( stderr, "W - Amp id {%x,%x} not supported yet\n", model[0], model[1] ); } @@ -459,209 +590,9 @@ Mustang::updateAmpObj( const unsigned char *data ) { } -void -Mustang::updateStompObj( const unsigned char *data ) { - - StompCC * new_stomp = NULL; - - const unsigned char *model = data + MODEL; - const unsigned char slot = data[FXSLOT]; - - if ( is_type(overdrive_id,model) ) { - new_stomp = new OverdriveCC( this, model, slot ); - } - else if ( is_type(wah_id,model) || - is_type(touch_wah_id,model) ) { - new_stomp = new WahCC( this, model, slot ); - } - else if ( is_type(fuzz_id,model) ) { - new_stomp = new FuzzCC( this, model, slot ); - } - else if ( is_type(fuzz_twah_id,model) ) { - new_stomp = new FuzzTouchWahCC( this, model, slot ); - } - else if ( is_type(simple_comp_id,model) ) { - new_stomp = new SimpleCompCC( this, model, slot ); - } - else if ( is_type(comp_id,model) ) { - new_stomp = new CompCC( this, model, slot ); - } - else if ( is_type(range_boost_id,model) ) { - new_stomp = new RangerCC( this, model, slot ); - } - else if ( is_type(green_box_id,model) ) { - new_stomp = new GreenBoxCC( this, model, slot ); - } - else if ( is_type(orange_box_id,model) ) { - new_stomp = new OrangeBoxCC( this, model, slot ); - } - else if ( is_type(black_box_id,model) ) { - new_stomp = new BlackBoxCC( this, model, slot ); - } - else if ( is_type(big_fuzz_id,model) ) { - new_stomp = new BigFuzzCC( this, model, slot ); - } - else { - fprintf( stderr, "W - Stomp id {%x,%x} not supported\n", model[0], model[1] ); - } - - if ( new_stomp!=NULL ) { - delete curr_stomp; - curr_stomp = new_stomp; - } -} - - -void -Mustang::updateDelayObj( const unsigned char *data ) { - - DelayCC * new_delay = NULL; - - const unsigned char *model = data + MODEL; - const unsigned char slot = data[FXSLOT]; - - if ( is_type(mono_dly_id,model) ) { - new_delay = new MonoDelayCC( this, model, slot ); - } - else if ( is_type(mono_filter_id,model) || - is_type(st_filter_id,model) ) { - new_delay = new EchoFilterCC( this, model, slot ); - } - else if ( is_type(mtap_dly_id,model) ) { - new_delay = new MultitapDelayCC( this, model, slot ); - } - else if ( is_type(pong_dly_id,model) ) { - new_delay = new PingPongDelayCC( this, model, slot ); - } - else if ( is_type(duck_dly_id,model) ) { - new_delay = new DuckingDelayCC( this, model, slot ); - } - else if ( is_type(reverse_dly_id,model) ) { - new_delay = new ReverseDelayCC( this, model, slot ); - } - else if ( is_type(tape_dly_id,model) ) { - new_delay = new TapeDelayCC( this, model, slot ); - } - else if ( is_type(st_tape_dly_id,model) ) { - new_delay = new StereoTapeDelayCC( this, model, slot ); - } - else { - fprintf( stderr, "W - Delay id {%x,%x} not supported\n", model[0], model[1] ); - } - - if ( new_delay!=NULL ) { - delete curr_delay; - curr_delay = new_delay; - } -} - - -void -Mustang::updateModObj( const unsigned char *data ) { - - ModCC * new_mod = NULL; - - const unsigned char *model = data + MODEL; - const unsigned char slot = data[FXSLOT]; - - if ( is_type(sine_chorus_id,model) || - is_type(tri_chorus_id,model) ) { - new_mod = new ChorusCC( this, model, slot ); - } - else if ( is_type(sine_flange_id,model) || - is_type(tri_flange_id,model) ) { - new_mod = new FlangerCC( this, model, slot ); - } - else if ( is_type(vibratone_id,model) ) { - new_mod = new VibratoneCC( this, model, slot ); - } - else if ( is_type(vint_trem_id,model) || - is_type(sine_trem_id,model) ) { - new_mod = new TremCC( this, model, slot ); - } - else if ( is_type(ring_mod_id,model) ) { - new_mod = new RingModCC( this, model, slot ); - } - else if ( is_type(step_filt_id,model) ) { - new_mod = new StepFilterCC( this, model, slot ); - } - else if ( is_type(phaser_id,model) ) { - new_mod = new PhaserCC( this, model, slot ); - } - else if ( is_type(pitch_shift_id,model) ) { - new_mod = new PitchShifterCC( this, model, slot ); - } - else if ( is_type(m_wah_id,model) || - is_type(m_touch_wah_id,model) ) { - new_mod = new ModWahCC( this, model, slot ); - } - else if ( is_type(dia_pitch_id,model) ) { - new_mod = new DiatonicShiftCC( this, model, slot ); - } - else { - fprintf( stderr, "W - Mod id {%x,%x} not supported\n", model[0], model[1] ); - } - - if ( new_mod!=NULL ) { - delete curr_mod; - curr_mod = new_mod; - } -} - - -void -Mustang::updateReverbObj( const unsigned char *data ) { - - const unsigned char *model = data + MODEL; - const unsigned char slot = data[FXSLOT]; - - delete curr_reverb; - curr_reverb = new ReverbCC( this, model, slot ); -} - - -int -Mustang::effectToggle(int cc, int value) { - if ( tuner_active ) return 0; - - int rc, count; - unsigned char buffer[64]; - - // Translate 23..26 --> 2..5 (current state index) - int state_index = cc - 21; - int state; - if ( value >= 0 && value <= 63 ) state = 1; - else if ( value > 63 && value <= 127 ) state = 0; - - memset(buffer, 0x00, 64); - buffer[0] = 0x19; - buffer[1] = 0xc3; - // Translate DSP to family - buffer[FAMILY] = dsp_parms[state_index][DSP] - 3; - // Invert logic - buffer[ACTIVE_INVERT] = state; - buffer[FXSLOT] = dsp_parms[state_index][FXSLOT]; -#if 0 - for ( int i=0; i<15; i++ ) fprintf( stderr, "%02x ", buffer[i] ); - fprintf( stderr, "\n" ); -#endif - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - - // Note: Toggle gets three response packets - for (int i=0; i < 3; i++) { - libusb_interrupt_transfer( usb_io, USB_IN, buffer, 64, &count, USB_TIMEOUT_MS ); - } - - return rc; -} - int Mustang::setAmp( int ord ) { if ( tuner_active ) return 0; - - int rc, count; - unsigned char scratch[64]; - unsigned char *buffer; switch (ord) { @@ -733,252 +664,86 @@ Mustang::setAmp( int ord ) { } } - // Setup amp personality - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - rc = libusb_interrupt_transfer( usb_io, USB_OUT, execute, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - // Copy to current setting store - memcpy(dsp_parms[AMP_STATE], buffer, 64); -// updateAmpObj("a"); - - // Setup USB gain - // memset(scratch, 0x00, 64); - // scratch[0] = 0x1c; - // scratch[1] = 0x03; - // scratch[2] = 0x0d; - // scratch[6] = 0x01; - // scratch[7] = 0x01; - // scratch[16] = 0x80; - - // rc = libusb_interrupt_transfer( usb_io, USB_OUT, scratch, 64, &count, USB_TIMEOUT_MS ); - // libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - // rc = libusb_interrupt_transfer( usb_io, USB_OUT, execute, 64, &count, USB_TIMEOUT_MS ); - // libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - return rc; + return executeModelChange( buffer ); } -int -Mustang::setReverb( int ord ) { + +int +Mustang::ampControl( int cc, int value ) { if ( tuner_active ) return 0; - int rc, count; - unsigned char scratch[64]; - - unsigned char *buffer; - - switch (ord) { - case 0: - buffer = reverb_none; - break; - case 1: - buffer = small_hall; - break; - case 2: - buffer = large_hall; - break; - case 3: - buffer = small_room; - break; - case 4: - buffer = large_room; - break; - case 5: - buffer = small_plate; - break; - case 6: - buffer = large_plate; - break; - case 7: - buffer = ambient; - break; - case 8: - buffer = arena; - break; - case 9: - buffer = spring_63; - break; - case 10: - buffer = spring_65; - break; - default: - fprintf( stderr, "W - Reverb select %d not supported\n", ord ); - return 0; - } - - buffer[FXSLOT] = dsp_parms[REVERB_STATE][FXSLOT]; - - // Setup amp personality - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - rc = libusb_interrupt_transfer( usb_io, USB_OUT, execute, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - // Copy to current setting store - memcpy(dsp_parms[REVERB_STATE], buffer, 64); - // updateReverbObj(); + unsigned char cmd[64]; + memset( cmd, 0, 64 ); + + pthread_mutex_lock( &dsp_sync[AMP_STATE].lock ); + int rc = curr_amp->dispatch( cc, value, cmd ); + pthread_mutex_unlock( &dsp_sync[AMP_STATE].lock ); + if ( rc<0 ) return rc; + rc = direct_control( cmd ); return rc; } -int -Mustang::setDelay( int ord ) { - if ( tuner_active ) return 0; - int rc, count; - unsigned char scratch[64]; - - unsigned char *buffer; +void +Mustang::updateStompObj( const unsigned char *data ) { - switch (ord) { - case 0: - buffer = delay_none; - break; - case 1: - buffer = mono_delay; - break; - case 2: - buffer = mono_echo_filter; - break; - case 3: - buffer = stereo_echo_filter; - break; - case 4: - buffer = multitap_delay; - break; - case 5: - buffer = ping_pong_delay; - break; - case 6: - buffer = ducking_delay; - break; - case 7: - buffer = reverse_delay; - break; - case 8: - buffer = tape_delay; - break; - case 9: - buffer = stereo_tape_delay; - break; - default: - fprintf( stderr, "W - Delay select %d not supported\n", ord ); - return 0; + StompCC * new_stomp = NULL; + + const unsigned char *model = data + MODEL; + const unsigned char slot = data[FXSLOT]; + + if ( is_type(overdrive_id,model) ) { + new_stomp = new OverdriveCC( this, model, slot ); + } + else if ( is_type(wah_id,model) || + is_type(touch_wah_id,model) ) { + new_stomp = new WahCC( this, model, slot ); + } + else if ( is_type(fuzz_id,model) ) { + new_stomp = new FuzzCC( this, model, slot ); + } + else if ( is_type(fuzz_twah_id,model) ) { + new_stomp = new FuzzTouchWahCC( this, model, slot ); + } + else if ( is_type(simple_comp_id,model) ) { + new_stomp = new SimpleCompCC( this, model, slot ); + } + else if ( is_type(comp_id,model) ) { + new_stomp = new CompCC( this, model, slot ); + } + else if ( is_type(range_boost_id,model) ) { + new_stomp = new RangerCC( this, model, slot ); + } + else if ( is_type(green_box_id,model) ) { + new_stomp = new GreenBoxCC( this, model, slot ); + } + else if ( is_type(orange_box_id,model) ) { + new_stomp = new OrangeBoxCC( this, model, slot ); + } + else if ( is_type(black_box_id,model) ) { + new_stomp = new BlackBoxCC( this, model, slot ); + } + else if ( is_type(big_fuzz_id,model) ) { + new_stomp = new BigFuzzCC( this, model, slot ); + } + else if ( is_type(null_stomp_id,model) ) { + new_stomp = new NullStompCC( this, model, 0 ); + } + else { + fprintf( stderr, "W - Stomp id {%x,%x} not supported\n", model[0], model[1] ); } - buffer[FXSLOT] = dsp_parms[DELAY_STATE][FXSLOT]; - - // Setup amp personality - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - rc = libusb_interrupt_transfer( usb_io, USB_OUT, execute, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - // Copy to current setting store - memcpy(dsp_parms[DELAY_STATE], buffer, 64); -// updateDelayObj(); - - return rc; -} - -int -Mustang::setMod( int ord ) { - if ( tuner_active ) return 0; - - int rc, count; - unsigned char scratch[64]; - - unsigned char *buffer; - - switch (ord) { - case 0: - buffer = mod_none; - break; - case 1: - buffer = sine_chorus; - break; - case 2: - buffer = triangle_chorus; - break; - case 3: - buffer = sine_flanger; - break; - case 4: - buffer = triangle_flanger; - break; - case 5: - buffer = vibratone; - break; - case 6: - buffer = vintage_tremolo; - break; - case 7: - buffer = sine_tremolo; - break; - case 8: - buffer = ring_modulator; - break; - case 9: - buffer = step_filter; - break; - case 10: - buffer = phaser; - break; - case 11: - buffer = pitch_shifter; - break; - default: - if ( isV2 ) { - switch (ord) { - case 12: - buffer = mod_wah; - break; - case 13: - buffer = mod_touch_wah; - break; - case 14: - buffer = diatonic_pitch_shift; - break; - default: - fprintf( stderr, "W - Mod select %d not supported\n", ord ); - return 0; - } - } - else { - fprintf( stderr, "W - Mod select %d not supported\n", ord ); - return 0; - } + if ( new_stomp!=NULL ) { + delete curr_stomp; + curr_stomp = new_stomp; } - - buffer[FXSLOT] = dsp_parms[MOD_STATE][FXSLOT]; - - // Setup amp personality - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - rc = libusb_interrupt_transfer( usb_io, USB_OUT, execute, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - - // Copy to current setting store - memcpy(dsp_parms[MOD_STATE], buffer, 64); - // updateModObj(); - - return rc; } + int Mustang::setStomp( int ord ) { if ( tuner_active ) return 0; - - int rc, count; - unsigned char scratch[64]; - unsigned char *buffer; switch (ord) { @@ -1041,81 +806,451 @@ Mustang::setStomp( int ord ) { } } - buffer[FXSLOT] = dsp_parms[STOMP_STATE][FXSLOT]; + pthread_mutex_lock( &dsp_sync[STOMP_STATE].lock ); + buffer[FXSLOT] = curr_stomp->getSlot(); + pthread_mutex_unlock( &dsp_sync[STOMP_STATE].lock ); + + return executeModelChange( buffer ); +} - // Setup amp personality - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); - rc = libusb_interrupt_transfer( usb_io, USB_OUT, execute, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, scratch, 64, &count, USB_TIMEOUT_MS ); +int +Mustang::stompControl( int cc, int value ) { + if ( tuner_active ) return 0; - // Copy to current setting store - memcpy(dsp_parms[STOMP_STATE], buffer, 64); -// updateStompObj(); + unsigned char cmd[64]; + memset( cmd, 0, 64 ); + + pthread_mutex_lock( &dsp_sync[STOMP_STATE].lock ); + int rc = curr_stomp->dispatch( cc, value, cmd ); + pthread_mutex_unlock( &dsp_sync[STOMP_STATE].lock ); + + if ( rc<0 ) return rc; + rc = direct_control( cmd ); + return rc; +} + + +void +Mustang::updateModObj( const unsigned char *data ) { + + ModCC * new_mod = NULL; + + const unsigned char *model = data + MODEL; + const unsigned char slot = data[FXSLOT]; + + if ( is_type(sine_chorus_id,model) || + is_type(tri_chorus_id,model) ) { + new_mod = new ChorusCC( this, model, slot ); + } + else if ( is_type(sine_flange_id,model) || + is_type(tri_flange_id,model) ) { + new_mod = new FlangerCC( this, model, slot ); + } + else if ( is_type(vibratone_id,model) ) { + new_mod = new VibratoneCC( this, model, slot ); + } + else if ( is_type(vint_trem_id,model) || + is_type(sine_trem_id,model) ) { + new_mod = new TremCC( this, model, slot ); + } + else if ( is_type(ring_mod_id,model) ) { + new_mod = new RingModCC( this, model, slot ); + } + else if ( is_type(step_filt_id,model) ) { + new_mod = new StepFilterCC( this, model, slot ); + } + else if ( is_type(phaser_id,model) ) { + new_mod = new PhaserCC( this, model, slot ); + } + else if ( is_type(pitch_shift_id,model) ) { + new_mod = new PitchShifterCC( this, model, slot ); + } + else if ( is_type(m_wah_id,model) || + is_type(m_touch_wah_id,model) ) { + new_mod = new ModWahCC( this, model, slot ); + } + else if ( is_type(dia_pitch_id,model) ) { + new_mod = new DiatonicShiftCC( this, model, slot ); + } + else if ( is_type(null_mod_id,model) ) { + new_mod = new NullModCC( this, model, 0 ); + } + else { + fprintf( stderr, "W - Mod id {%x,%x} not supported\n", model[0], model[1] ); + } + + if ( new_mod!=NULL ) { + delete curr_mod; + curr_mod = new_mod; + } +} + + +int +Mustang::setMod( int ord ) { + if ( tuner_active ) return 0; + unsigned char *buffer; + + switch (ord) { + case 0: + buffer = mod_none; + break; + case 1: + buffer = sine_chorus; + break; + case 2: + buffer = triangle_chorus; + break; + case 3: + buffer = sine_flanger; + break; + case 4: + buffer = triangle_flanger; + break; + case 5: + buffer = vibratone; + break; + case 6: + buffer = vintage_tremolo; + break; + case 7: + buffer = sine_tremolo; + break; + case 8: + buffer = ring_modulator; + break; + case 9: + buffer = step_filter; + break; + case 10: + buffer = phaser; + break; + case 11: + buffer = pitch_shifter; + break; + default: + if ( isV2 ) { + switch (ord) { + case 12: + buffer = mod_wah; + break; + case 13: + buffer = mod_touch_wah; + break; + case 14: + buffer = diatonic_pitch_shift; + break; + default: + fprintf( stderr, "W - Mod select %d not supported\n", ord ); + return 0; + } + } + else { + fprintf( stderr, "W - Mod select %d not supported\n", ord ); + return 0; + } + } + + pthread_mutex_lock( &dsp_sync[MOD_STATE].lock ); + buffer[FXSLOT] = curr_mod->getSlot(); + pthread_mutex_unlock( &dsp_sync[MOD_STATE].lock ); + + return executeModelChange( buffer ); +} + + +int +Mustang::modControl( int cc, int value ) { + if ( tuner_active ) return 0; + + unsigned char cmd[64]; + memset( cmd, 0, 64 ); + + pthread_mutex_lock( &dsp_sync[MOD_STATE].lock ); + int rc = curr_mod->dispatch( cc, value, cmd ); + pthread_mutex_unlock( &dsp_sync[MOD_STATE].lock ); + + if ( rc<0 ) return rc; + rc = direct_control( cmd ); + return rc; +} + + +void +Mustang::updateDelayObj( const unsigned char *data ) { + + DelayCC * new_delay = NULL; + + const unsigned char *model = data + MODEL; + const unsigned char slot = data[FXSLOT]; + + if ( is_type(mono_dly_id,model) ) { + new_delay = new MonoDelayCC( this, model, slot ); + } + else if ( is_type(mono_filter_id,model) || + is_type(st_filter_id,model) ) { + new_delay = new EchoFilterCC( this, model, slot ); + } + else if ( is_type(mtap_dly_id,model) ) { + new_delay = new MultitapDelayCC( this, model, slot ); + } + else if ( is_type(pong_dly_id,model) ) { + new_delay = new PingPongDelayCC( this, model, slot ); + } + else if ( is_type(duck_dly_id,model) ) { + new_delay = new DuckingDelayCC( this, model, slot ); + } + else if ( is_type(reverse_dly_id,model) ) { + new_delay = new ReverseDelayCC( this, model, slot ); + } + else if ( is_type(tape_dly_id,model) ) { + new_delay = new TapeDelayCC( this, model, slot ); + } + else if ( is_type(st_tape_dly_id,model) ) { + new_delay = new StereoTapeDelayCC( this, model, slot ); + } + else if ( is_type(null_dly_id,model) ) { + new_delay = new NullDelayCC( this, model, 0 ); + } + else { + fprintf( stderr, "W - Delay id {%x,%x} not supported\n", model[0], model[1] ); + } + + if ( new_delay!=NULL ) { + delete curr_delay; + curr_delay = new_delay; + } +} + + +int +Mustang::setDelay( int ord ) { + if ( tuner_active ) return 0; + unsigned char *buffer; + + switch (ord) { + case 0: + buffer = delay_none; + break; + case 1: + buffer = mono_delay; + break; + case 2: + buffer = mono_echo_filter; + break; + case 3: + buffer = stereo_echo_filter; + break; + case 4: + buffer = multitap_delay; + break; + case 5: + buffer = ping_pong_delay; + break; + case 6: + buffer = ducking_delay; + break; + case 7: + buffer = reverse_delay; + break; + case 8: + buffer = tape_delay; + break; + case 9: + buffer = stereo_tape_delay; + break; + default: + fprintf( stderr, "W - Delay select %d not supported\n", ord ); + return 0; + } + + pthread_mutex_lock( &dsp_sync[DELAY_STATE].lock ); + buffer[FXSLOT] = curr_delay->getSlot(); + pthread_mutex_unlock( &dsp_sync[DELAY_STATE].lock ); + + return executeModelChange( buffer ); +} + + +int +Mustang::delayControl( int cc, int value ) { + if ( tuner_active ) return 0; + + unsigned char cmd[64]; + memset( cmd, 0, 64 ); + + pthread_mutex_lock( &dsp_sync[DELAY_STATE].lock ); + int rc = curr_delay->dispatch( cc, value, cmd ); + pthread_mutex_unlock( &dsp_sync[DELAY_STATE].lock ); + + if ( rc<0 ) return rc; + rc = direct_control( cmd ); + return rc; +} + + +void +Mustang::updateReverbObj( const unsigned char *data ) { + + const unsigned char *model = data + MODEL; + const unsigned char slot = data[FXSLOT]; + + delete curr_reverb; + + if ( is_type(null_reverb_id,model) ) { + curr_reverb = new NullReverbCC( this, model, 0 ); + } + else { + curr_reverb = new ReverbCC( this, model, slot ); + } +} + + +int +Mustang::setReverb( int ord ) { + if ( tuner_active ) return 0; + unsigned char *buffer; + + switch (ord) { + case 0: + buffer = reverb_none; + break; + case 1: + buffer = small_hall; + break; + case 2: + buffer = large_hall; + break; + case 3: + buffer = small_room; + break; + case 4: + buffer = large_room; + break; + case 5: + buffer = small_plate; + break; + case 6: + buffer = large_plate; + break; + case 7: + buffer = ambient; + break; + case 8: + buffer = arena; + break; + case 9: + buffer = spring_63; + break; + case 10: + buffer = spring_65; + break; + default: + fprintf( stderr, "W - Reverb select %d not supported\n", ord ); + return 0; + } + + pthread_mutex_lock( &dsp_sync[REVERB_STATE].lock ); + buffer[FXSLOT] = curr_reverb->getSlot(); + pthread_mutex_unlock( &dsp_sync[REVERB_STATE].lock ); + + return executeModelChange( buffer ); +} + + +int +Mustang::reverbControl( int cc, int value ) { + if ( tuner_active ) return 0; + + unsigned char cmd[64]; + memset( cmd, 0, 64 ); + + pthread_mutex_lock( &dsp_sync[REVERB_STATE].lock ); + int rc = curr_reverb->dispatch( cc, value, cmd ); + pthread_mutex_unlock( &dsp_sync[REVERB_STATE].lock ); + + if ( rc<0 ) return rc; + rc = direct_control( cmd ); + return rc; +} + + +int +Mustang::effectToggle(int cc, int value) { + if ( tuner_active ) return 0; + + unsigned char buffer[64]; + memset(buffer, 0x00, 64); + + int toggle; + if ( value >= 0 && value <= 63 ) toggle = 1; + else if ( value > 63 && value <= 127 ) toggle = 0; + + buffer[0] = 0x19; + buffer[1] = 0xc3; + + // Translate 23..26 --> 3..6 (EFX family) + int family = cc - 20; + buffer[2] = family; + + // Invert logic + buffer[3] = toggle; + + // Translate 23..26 --> 1..4 (index into dsp parms array) + int state_index = cc - 22; + + pthread_mutex_lock( &efx_toggle_sync.lock ); + + unsigned char slot; + switch ( state_index ) { + case 1: + slot = curr_stomp->getSlot(); + break; + case 2: + slot = curr_mod->getSlot(); + break; + case 3: + slot = curr_delay->getSlot(); + break; + case 4: + slot = curr_reverb->getSlot(); + break; + } + buffer[4] = slot; + + efx_toggle_sync.value = false; + + int rc = sendCmd( buffer ); + + while ( ! efx_toggle_sync.value ) pthread_cond_wait( &efx_toggle_sync.cond, &efx_toggle_sync.lock ); + pthread_mutex_unlock( &efx_toggle_sync.lock ); + +#ifdef DEBUG + fprintf( stderr, "DEBUG: Efx toggle done\n" ); +#endif return rc; } int -Mustang::continuous_control( const Mustang::Cmd & cmd ) { - if ( tuner_active ) return 0; - - int rc, count; - unsigned char buffer[64]; - - memset(buffer, 0x00, 64); +Mustang::direct_control( unsigned char *buffer ) { buffer[0] = 0x05; buffer[1] = 0xc3; - buffer[2] = cmd.parm2; - buffer[3] = dsp_parms[cmd.state_index][MODEL]; - // target parameter - buffer[5] = cmd.parm5; - buffer[6] = cmd.parm6; - buffer[7] = cmd.parm7; - - // Scale and clamp to valid index range - int index = (int) ceil( (double)cmd.value * magic_scale_factor ); - if ( index > magic_max ) index = magic_max; - - unsigned short eff_value = magic_values[index]; + pthread_mutex_lock( &cc_ack_sync.lock ); + cc_ack_sync.value = false; + + int rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; - buffer[9] = eff_value & 0xff; - buffer[10] = (eff_value >> 8) & 0xff; + while ( ! cc_ack_sync.value ) pthread_cond_wait( &cc_ack_sync.cond, &cc_ack_sync.lock ); + pthread_mutex_unlock( &cc_ack_sync.lock ); - // Send command and flush reply - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, buffer, 64, &count, USB_TIMEOUT_MS ); - - return rc; -} - - -int -Mustang::discrete_control( const Mustang::Cmd & cmd ) { - if ( tuner_active ) return 0; - - int rc, count; - unsigned char buffer[64]; - - memset(buffer, 0x00, 64); - buffer[0] = 0x05; - buffer[1] = 0xc3; - buffer[2] = cmd.parm2; - buffer[3] = dsp_parms[cmd.state_index][MODEL]; - - buffer[5] = cmd.parm5; - buffer[6] = cmd.parm6; - buffer[7] = cmd.parm7; - - // Discrete value - buffer[9] = cmd.value; - - // Send command and flush reply - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); - libusb_interrupt_transfer( usb_io, USB_IN, buffer, 64, &count, USB_TIMEOUT_MS ); +#ifdef DEBUG + fprintf( stderr, "DEBUG: Direct control done\n" ); +#endif return rc; } @@ -1125,31 +1260,71 @@ int Mustang::patchChange( int patch ) { if ( tuner_active ) return 0; - int rc, count; - unsigned char buffer[64], data[7][64]; - + unsigned char buffer[64]; memset(buffer, 0x00, 64); + buffer[0] = 0x1c; buffer[1] = 0x01; buffer[2] = 0x01; - buffer[PATCH_SLOT] = patch; + buffer[4] = patch; buffer[6] = 0x01; - rc = libusb_interrupt_transfer( usb_io, USB_OUT, buffer, 64, &count, USB_TIMEOUT_MS ); + pthread_mutex_lock( &cc_ack_eom.lock ); + cc_ack_eom.value = false; + + int rc = sendCmd( buffer ); + + while ( ! cc_ack_eom.value ) pthread_cond_wait( &cc_ack_eom.cond, &cc_ack_eom.lock ); + pthread_mutex_unlock( &cc_ack_eom.lock ); + +#ifdef DEBUG + fprintf( stderr, "DEBUG: Leaving patch change\n" ); +#endif - // Mustang III has nine responses - for(int i=0; i < 9; i++) { - libusb_interrupt_transfer( usb_io, USB_IN, buffer, 64, &count, USB_TIMEOUT_MS ); - int dsp = buffer[2]; - if ( dsp >= 4 && dsp <= 9 ) - memcpy(dsp_parms[dsp - 4], buffer, 64); - } -// updateAmpObj("a"); -// updateReverbObj(); -// updateDelayObj(); -// updateModObj(); -// updateStompObj(); - return rc; } + +int +Mustang::tunerMode( int value ) { + int rc; + + unsigned char buffer[64]; + memset(buffer, 0x00, 64); + + buffer[0] = 0x0a; + buffer[1] = 0x01; + + bool want_active = ((value > 63) && (value <= 127)) ? true : false; + if ( want_active == tuner_active ) return 0; + + pthread_mutex_lock( &tuner_ack_sync.lock ); + tuner_ack_sync.value = false; + + if ( want_active ) { + // Tuner on + buffer[2] = buffer[3] = buffer[4] = 0x01; + rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; + + tuner_active = true; + } + else { + // Tuner off + rc = sendCmd( buffer ); + if ( rc!=0 ) return rc; + + tuner_active = false; + } + + while ( ! tuner_ack_sync.value ) pthread_cond_wait( &tuner_ack_sync.cond, &tuner_ack_sync.lock ); + pthread_mutex_unlock( &tuner_ack_sync.lock ); + +#ifdef DEBUG + fprintf( stderr, "DEBUG: Done tuner toggle\n" ); +#endif + + return 0; +} + + diff --git a/mustang.h b/mustang.h index fb88484..ad3c46e 100644 --- a/mustang.h +++ b/mustang.h @@ -20,37 +20,18 @@ class DelayCC; class ModCC; class StompCC; -class Mustang { - friend class AmpCC; - friend class ReverbCC; - friend class DelayCC; - friend class ModCC; - friend class StompCC; - - char preset_names[100][33]; - unsigned curr_preset_idx; - - unsigned char dsp_parms[6][64]; - unsigned char curr_model[5][2]; +class Mustang { unsigned char execute[64]; static const unsigned char state_prefix[]; - static const unsigned char parms_done[]; - - static const unsigned char tuner_ack[]; static const unsigned char tuner_prefix[]; - - static const unsigned char select_ack[]; - static const unsigned char cc_ack[]; libusb_device_handle *usb_io; pthread_t worker; - pthread_mutex_t data_lock = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_t shutdown_lock = PTHREAD_MUTEX_INITIALIZER; bool want_shutdown; @@ -66,14 +47,36 @@ class Mustang { } }; - // Manage access to each DSP block - Condition dsp_sync[5]; - Condition preset_names_sync; + char preset_names[100][33]; + unsigned curr_preset_idx; + + // Manage access to each DSP block + Condition dsp_sync[6]; + unsigned char dsp_parms[6][64]; + + // Received {0x1c, 0x01, 0x00, ...} + Condition cc_ack_eom; + + // Received {0x00, 0x00, 0x19, ... } + Condition efx_toggle_sync; + static const unsigned char efx_toggle_ack[]; // Synchronize init on end of initial parm dump Condition parm_read_sync; + static const unsigned char parm_read_ack[]; + // Synchronize on receipt of model change acknowledge + Condition model_change_sync; + static const unsigned char model_change_ack[]; + + // Synchronize on receipt of control change acknowledge + Condition cc_ack_sync; + static const unsigned char cc_ack[]; + + Condition tuner_ack_sync; + static const unsigned char tuner_ack[]; + struct usb_id { // product id int pid; @@ -87,31 +90,24 @@ class Mustang { static const usb_id amp_ids[]; bool isV2; - static void *threadStarter( void * ); - void handleInput( void ); - bool tuner_active; AmpCC * curr_amp; - ReverbCC * curr_reverb; - DelayCC * curr_delay; - ModCC * curr_mod; + StompCC * curr_stomp; + ModCC * curr_mod; + DelayCC * curr_delay; + ReverbCC * curr_reverb; -public: - struct Cmd { - int state_index; - int parm2; - int parm5; - int parm6; - int parm7; - int value; - }; + static void *threadStarter( void * ); + void handleInput( void ); -private: - int continuous_control( const Mustang::Cmd & cmd ); - int discrete_control( const Mustang::Cmd & cmd ); + int direct_control( unsigned char *cmd ); + int sendCmd( unsigned char *buffer ); + int requestDump( void ); + int executeModelChange( unsigned char *buffer ); + void updateAmpObj( const unsigned char *data ); void updateStompObj( const unsigned char *data ); void updateReverbObj( const unsigned char *data ); @@ -132,22 +128,25 @@ public: int commShutdown( void ); int setAmp( int ord ); - int setReverb( int ord ); - int setDelay( int ord ); - int setMod( int ord ); + int ampControl( int cc, int value ); + int setStomp( int ord ); + int stompControl( int cc, int value ); + + int setMod( int ord ); + int modControl( int cc, int value ); + + int setDelay( int ord ); + int delayControl( int cc, int value ); + + int setReverb( int ord ); + int reverbControl( int cc, int value ); int tunerMode( int value ); int patchChange( int ); int effectToggle( int cc, int value ); - - AmpCC * getAmp( void ) { return curr_amp;} - ReverbCC * getReverb( void ) { return curr_reverb;} - DelayCC * getDelay( void ) { return curr_delay;} - ModCC * getMod( void ) { return curr_mod;} - StompCC * getStomp( void ) { return curr_stomp;} }; diff --git a/mustang_midi.cpp b/mustang_midi.cpp index 6501ebd..1d6aeef 100644 --- a/mustang_midi.cpp +++ b/mustang_midi.cpp @@ -7,26 +7,16 @@ #include "mustang.h" -#if 0 -#include "amp.h" -#include "reverb.h" -#include "delay.h" -#include "mod.h" -#include "stomp.h" -#endif - static Mustang mustang; static int channel; -#if 0 void message_action( double deltatime, std::vector< unsigned char > *message, void *userData ) { #if 0 unsigned int nBytes = message->size(); - if ( nBytes > 0 ) { - fprintf( stdout, "%02x %d %d\n", (int)message->at(0), (int)message->at(1), (int)message->at(2) ); - } + if ( nBytes == 2 ) fprintf( stdout, "%02x %d\n", (int)message->at(0), (int)message->at(1) ); + else if ( nBytes == 3 ) fprintf( stdout, "%02x %d %d\n", (int)message->at(0), (int)message->at(1), (int)message->at(2) ); #endif // Is this for us? @@ -40,7 +30,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo case 0xc0: { // Program change int bank = (int)(*message)[1]; - int rc = mustang.load_memory_bank( bank ); + int rc = mustang.patchChange( bank ); if ( rc ) { fprintf( stderr, "Error: PC#%d failed. RC = %d\n", bank, rc ); } @@ -59,20 +49,20 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo } // All EFX toggle else if ( cc == 22 ) { - rc = mustang.effect_toggle( 23, value ); + rc = mustang.effectToggle( 23, value ); if ( rc == 0 ) { - rc = mustang.effect_toggle( 24, value ); + rc = mustang.effectToggle( 24, value ); if ( rc == 0 ) { - rc = mustang.effect_toggle( 25, value ); + rc = mustang.effectToggle( 25, value ); if ( rc == 0 ) { - rc = mustang.effect_toggle( 26, value ); + rc = mustang.effectToggle( 26, value ); } } } } // Effects on/off else if ( cc >= 23 && cc <= 26 ) { - rc = mustang.effect_toggle( cc, value ); + rc = mustang.effectToggle( cc, value ); } // Set stomp model else if ( cc == 28 ) { @@ -80,8 +70,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo } // Stomp CC handler else if ( cc >= 29 && cc <= 33 ) { - StompCC *stompObj = mustang.getStomp(); - rc = stompObj->dispatch( cc, value ); + rc = mustang.stompControl( cc, value ); } // Set mod model else if ( cc == 38 ) { @@ -89,8 +78,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo } // Mod CC handler else if ( cc >= 39 && cc <= 43 ) { - ModCC *modObj = mustang.getMod(); - rc = modObj->dispatch( cc, value ); + rc = mustang.modControl( cc, value ); } // Set delay model else if ( cc == 48 ) { @@ -98,8 +86,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo } // Delay CC handler else if ( cc >= 49 && cc <= 54 ) { - DelayCC *delayObj = mustang.getDelay(); - rc = delayObj->dispatch( cc, value ); + rc = mustang.delayControl( cc, value ); } // Set reverb model else if ( cc == 58 ) { @@ -107,8 +94,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo } // Reverb CC handler else if ( cc >= 59 && cc <= 63 ) { - ReverbCC *reverbObj = mustang.getReverb(); - rc = reverbObj->dispatch( cc, value ); + rc = mustang.reverbControl( cc, value ); } // Set amp model else if ( cc == 68 ) { @@ -116,8 +102,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo } // Amp CC Handler else if ( cc >= 69 && cc <= 79 ) { - AmpCC *ampObj = mustang.getAmp(); - rc = ampObj->dispatch( cc, value ); + rc = mustang.ampControl( cc, value ); } if ( rc ) { fprintf( stderr, "Error: CC#%d failed. RC = %d\n", cc, rc ); @@ -131,8 +116,6 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo } -#endif - // void errorcallback( RtError::Type type, const std::string & detail, void *userData ) { // std::cout << "Error: Code = " << type << ", Msg: " << detail << "\n"; // } @@ -166,9 +149,6 @@ int main( int argc, const char **argv ) { exit( 1 ); } - fprintf( stderr, "Setup done!\n" ); - -#if 0 RtMidiIn *input_handler = new RtMidiIn(); // See if we have any ports @@ -185,8 +165,6 @@ int main( int argc, const char **argv ) { // Don't want sysex, timing, active sense input_handler->ignoreTypes( true, true, true ); -#endif - // Block and wait for signal pause(); @@ -199,8 +177,6 @@ int main( int argc, const char **argv ) { exit( 1 ); } - fprintf( stderr, "Shutdown complete!\n" ); - // delete input_handler; return 0; diff --git a/reverb.cpp b/reverb.cpp index 5b5877b..8e5b72d 100644 --- a/reverb.cpp +++ b/reverb.cpp @@ -1,44 +1,44 @@ #include "reverb.h" -#include "mustang.h" -#include "constants.h" +#include "magic.h" int -ReverbCC::continuous_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = REVERB_STATE; - cmd.parm2 = 0x06; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; - - return amp->continuous_control( cmd ); +ReverbCC::continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x06; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; + + unsigned short magic = magic_values[value]; + cmd[9] = magic & 0xff; + cmd[10] = (magic >> 8) & 0xff; + return 0; } int -ReverbCC::dispatch( int cc, int value ) { +ReverbCC::dispatch( int cc, int value, unsigned char *cmd ) { switch ( cc ) { case 59: // Level - return cc59( value ); + return cc59( value, cmd ); break; case 60: // Decay - return cc60( value ); + return cc60( value, cmd ); break; case 61: // Dwell - return cc61( value ); + return cc61( value, cmd ); break; case 62: // Diffusion - return cc62( value ); + return cc62( value, cmd ); break; case 63: // Tone - return cc63( value ); + return cc63( value, cmd ); break; default: return 0; diff --git a/reverb.h b/reverb.h index 3bb4ec8..e03f7be 100644 --- a/reverb.h +++ b/reverb.h @@ -14,7 +14,7 @@ protected: unsigned char model[2]; unsigned char slot; - int continuous_control( int parm5, int parm6, int parm7, int value ); + int continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); public: ReverbCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : @@ -24,21 +24,21 @@ public: memcpy( this->model, model, 2 ); } - int dispatch( int cc, int value ); + int dispatch( int cc, int value, unsigned char *cmd ); const unsigned char *getModel( void ) { return model;} const unsigned char getSlot( void ) { return slot;} private: // Level - int cc59( int value ) { return continuous_control( 0x00, 0x00, 0x0b, value );} + int cc59( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x0b, value, cmd );} // Decay - int cc60( int value ) { return continuous_control( 0x01, 0x01, 0x0b, value );} + int cc60( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x0b, value, cmd );} // Dwell - int cc61( int value ) { return continuous_control( 0x02, 0x02, 0x0b, value );} + int cc61( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x0b, value, cmd );} // Diffusion - int cc62( int value ) { return continuous_control( 0x03, 0x03, 0x0b, value );} + int cc62( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x0b, value, cmd );} // Tone - int cc63( int value ) { return continuous_control( 0x04, 0x04, 0x0b, value );} + int cc63( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x0b, value, cmd );} }; @@ -46,11 +46,11 @@ class NullReverbCC : public ReverbCC { public: NullReverbCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : ReverbCC(theAmp,model,theSlot) {} private: - int cc59( int value ) { return 0;} - int cc60( int value ) { return 0;} - int cc61( int value ) { return 0;} - int cc62( int value ) { return 0;} - int cc63( int value ) { return 0;} + int cc59( int value, unsigned char *cmd ) { return -1;} + int cc60( int value, unsigned char *cmd ) { return -1;} + int cc61( int value, unsigned char *cmd ) { return -1;} + int cc62( int value, unsigned char *cmd ) { return -1;} + int cc63( int value, unsigned char *cmd ) { return -1;} }; diff --git a/reverb_models.cpp b/reverb_models.cpp new file mode 100644 index 0000000..36a1b38 --- /dev/null +++ b/reverb_models.cpp @@ -0,0 +1,4 @@ +#include "reverb_models.h" + +const unsigned char null_reverb_id[] = { 0x00, 0x00 }; + diff --git a/reverb_models.h b/reverb_models.h new file mode 100644 index 0000000..fcc2508 --- /dev/null +++ b/reverb_models.h @@ -0,0 +1,8 @@ +// -*-c++-*- + +#ifndef REVERB_MODELS_H +#define REVERB_MODELS_H + +extern const unsigned char null_reverb_id[]; + +#endif diff --git a/stomp.cpp b/stomp.cpp index 6595ada..6e2cead 100644 --- a/stomp.cpp +++ b/stomp.cpp @@ -1,57 +1,56 @@ #include "stomp.h" -#include "mustang.h" -#include "constants.h" +#include "magic.h" int -StompCC::continuous_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = STOMP_STATE; - cmd.parm2 = 0x03; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; - - return amp->continuous_control( cmd ); +StompCC::continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x03; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; + + unsigned short magic = magic_values[value]; + cmd[9] = magic & 0xff; + cmd[10] = (magic >> 8) & 0xff; + return 0; } int -StompCC::discrete_control( int parm5, int parm6, int parm7, int value ) { - Mustang::Cmd cmd; - cmd.state_index = STOMP_STATE; - cmd.parm2 = 0x03; - cmd.parm5 = parm5; - cmd.parm6 = parm6; - cmd.parm7 = parm7; - cmd.value = value; +StompCC::discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ) { + cmd[2] = 0x03; + memcpy( cmd + 3, model, 2 ); + cmd[5] = parm5; + cmd[6] = parm6; + cmd[7] = parm7; - return amp->discrete_control( cmd ); + cmd[9] = value; + return 0; } int -StompCC::dispatch( int cc, int value ) { +StompCC::dispatch( int cc, int value, unsigned char *cmd ) { switch ( cc ) { case 29: // Level / Mix / Type - return cc29( value ); + return cc29( value, cmd ); break; case 30: // Gain / Freq / Sens / Thresh - return cc30( value ); + return cc30( value, cmd ); break; case 31: // Low / Heel Freq / Octave / Sens / Ratio - return cc31( value ); + return cc31( value, cmd ); break; case 32: // Mid / Toe Freq / Low / Octave / Attack - return cc32( value ); + return cc32( value, cmd ); break; case 33: // High / High Q / Peak / Relase - return cc33( value ); + return cc33( value, cmd ); break; default: return 0; diff --git a/stomp.h b/stomp.h index 8132756..6a315e5 100644 --- a/stomp.h +++ b/stomp.h @@ -14,8 +14,8 @@ protected: unsigned char model[2]; unsigned char slot; - int continuous_control( int parm5, int parm6, int parm7, int value ); - int discrete_control( int parm5, int parm6, int parm7, int value ); + int continuous_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); + int discrete_control( int parm5, int parm6, int parm7, int value, unsigned char *cmd ); public: StompCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : @@ -25,16 +25,16 @@ public: memcpy( this->model, model, 2 ); } - int dispatch( int cc, int value ); + int dispatch( int cc, int value, unsigned char *cmd ); const unsigned char *getModel( void ) { return model;} const unsigned char getSlot( void ) { return slot;} private: - virtual int cc29( int value ) = 0; - virtual int cc30( int value ) = 0; - virtual int cc31( int value ) = 0; - virtual int cc32( int value ) = 0; - virtual int cc33( int value ) = 0; + virtual int cc29( int value, unsigned char *cmd ) = 0; + virtual int cc30( int value, unsigned char *cmd ) = 0; + virtual int cc31( int value, unsigned char *cmd ) = 0; + virtual int cc32( int value, unsigned char *cmd ) = 0; + virtual int cc33( int value, unsigned char *cmd ) = 0; }; @@ -43,15 +43,15 @@ public: OverdriveCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Gain - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Low - virtual int cc31( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Mid - virtual int cc32( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc32( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // High - virtual int cc33( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc33( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -60,17 +60,17 @@ public: WahCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Mix - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Freq - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Heel Freq - virtual int cc31( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Toe Freq - virtual int cc32( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc32( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // High Q - virtual int cc33( int value ) { - if ( value > 1 ) return 0; - else return discrete_control( 0x04, 0x04, 0x81, value ); + virtual int cc33( int value, unsigned char *cmd ) { + if ( value > 1 ) return -1; + else return discrete_control( 0x04, 0x04, 0x81, value, cmd ); } }; @@ -80,15 +80,15 @@ public: FuzzCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Gain - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Octave - virtual int cc31( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Low - virtual int cc32( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc32( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // High - virtual int cc33( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc33( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -97,15 +97,15 @@ public: FuzzTouchWahCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Gain - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Sens - virtual int cc31( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Octave - virtual int cc32( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc32( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Peak - virtual int cc33( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc33( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -114,14 +114,14 @@ public: SimpleCompCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Type - virtual int cc29( int value ) { - if ( value > 3 ) return 0; - else return discrete_control( 0x00, 0x05, 0x92, value ); + virtual int cc29( int value, unsigned char *cmd ) { + if ( value > 3 ) return -1; + else return discrete_control( 0x00, 0x05, 0x92, value, cmd ); } - virtual int cc30( int value ) { return 0;} - virtual int cc31( int value ) { return 0;} - virtual int cc32( int value ) { return 0;} - virtual int cc33( int value ) { return 0;} + virtual int cc30( int value, unsigned char *cmd ) { return -1;} + virtual int cc31( int value, unsigned char *cmd ) { return -1;} + virtual int cc32( int value, unsigned char *cmd ) { return -1;} + virtual int cc33( int value, unsigned char *cmd ) { return -1;} }; @@ -130,15 +130,15 @@ public: CompCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Thresh - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Ratio - virtual int cc31( int value ) { return continuous_control( 0x02, 0x02, 0x04, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x04, value, cmd );} // Attack - virtual int cc32( int value ) { return continuous_control( 0x03, 0x03, 0x01, value );} + virtual int cc32( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x01, value, cmd );} // Release - virtual int cc33( int value ) { return continuous_control( 0x04, 0x04, 0x01, value );} + virtual int cc33( int value, unsigned char *cmd ) { return continuous_control( 0x04, 0x04, 0x01, value, cmd );} }; @@ -147,15 +147,15 @@ public: RangerCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Gain - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Lo-Cut - virtual int cc31( int value ) { return continuous_control( 0x02, 0x03, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x03, 0x01, value, cmd );} // Bright - virtual int cc32( int value ) { return continuous_control( 0x03, 0x02, 0x01, value );} + virtual int cc32( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x02, 0x01, value, cmd );} // n/a - virtual int cc33( int value ) { return 0;} + virtual int cc33( int value, unsigned char *cmd ) { return -1;} }; @@ -164,15 +164,15 @@ public: GreenBoxCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Gain - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Tone - virtual int cc31( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // Bright - virtual int cc32( int value ) { return continuous_control( 0x03, 0x03, 0x12, value );} + virtual int cc32( int value, unsigned char *cmd ) { return continuous_control( 0x03, 0x03, 0x12, value, cmd );} // n/a - virtual int cc33( int value ) { return 0;} + virtual int cc33( int value, unsigned char *cmd ) { return -1;} }; @@ -181,15 +181,15 @@ public: OrangeBoxCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Dist - virtual int cc30( int value ) { return continuous_control( 0x01, 0x02, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x02, 0x01, value, cmd );} // Tone - virtual int cc31( int value ) { return continuous_control( 0x02, 0x01, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x01, 0x01, value, cmd );} // n/a - virtual int cc32( int value ) { return 0;} + virtual int cc32( int value, unsigned char *cmd ) { return -1;} // n/a - virtual int cc33( int value ) { return 0;} + virtual int cc33( int value, unsigned char *cmd ) { return -1;} }; @@ -198,15 +198,15 @@ public: BlackBoxCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Dist - virtual int cc30( int value ) { return continuous_control( 0x01, 0x02, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x02, 0x01, value, cmd );} // Filter - virtual int cc31( int value ) { return continuous_control( 0x02, 0x01, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x01, 0x01, value, cmd );} // n/a - virtual int cc32( int value ) { return 0;} + virtual int cc32( int value, unsigned char *cmd ) { return -1;} // n/a - virtual int cc33( int value ) { return 0;} + virtual int cc33( int value, unsigned char *cmd ) { return -1;} }; @@ -215,15 +215,15 @@ public: BigFuzzCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: // Level - virtual int cc29( int value ) { return continuous_control( 0x00, 0x00, 0x01, value );} + virtual int cc29( int value, unsigned char *cmd ) { return continuous_control( 0x00, 0x00, 0x01, value, cmd );} // Tone - virtual int cc30( int value ) { return continuous_control( 0x01, 0x01, 0x01, value );} + virtual int cc30( int value, unsigned char *cmd ) { return continuous_control( 0x01, 0x01, 0x01, value, cmd );} // Sustain - virtual int cc31( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );} + virtual int cc31( int value, unsigned char *cmd ) { return continuous_control( 0x02, 0x02, 0x01, value, cmd );} // n/a - virtual int cc32( int value ) { return 0;} + virtual int cc32( int value, unsigned char *cmd ) { return -1;} // n/a - virtual int cc33( int value ) { return 0;} + virtual int cc33( int value, unsigned char *cmd ) { return -1;} }; @@ -231,11 +231,11 @@ class NullStompCC : public StompCC { public: NullStompCC( Mustang * theAmp, const unsigned char *model, const unsigned char theSlot ) : StompCC(theAmp,model,theSlot) {} private: - virtual int cc29( int value ) { return 0;} - virtual int cc30( int value ) { return 0;} - virtual int cc31( int value ) { return 0;} - virtual int cc32( int value ) { return 0;} - virtual int cc33( int value ) { return 0;} + virtual int cc29( int value, unsigned char *cmd ) { return -1;} + virtual int cc30( int value, unsigned char *cmd ) { return -1;} + virtual int cc31( int value, unsigned char *cmd ) { return -1;} + virtual int cc32( int value, unsigned char *cmd ) { return -1;} + virtual int cc33( int value, unsigned char *cmd ) { return -1;} }; diff --git a/stomp_models.cpp b/stomp_models.cpp index 54d5a3e..f700405 100644 --- a/stomp_models.cpp +++ b/stomp_models.cpp @@ -1,5 +1,7 @@ #include "stomp_models.h" +const unsigned char null_stomp_id[] = { 0x00, 0x00 }; + const unsigned char overdrive_id[] = { 0x3c, 0x00 }; const unsigned char wah_id[] = { 0x49, 0x00 }; const unsigned char touch_wah_id[] = { 0x4a, 0x00 }; diff --git a/stomp_models.h b/stomp_models.h index f2379b0..839dda2 100644 --- a/stomp_models.h +++ b/stomp_models.h @@ -1,6 +1,8 @@ #ifndef STOMP_MODELS_H #define STOMP_MODELS_H +extern const unsigned char null_stomp_id[]; + extern const unsigned char overdrive_id[]; extern const unsigned char wah_id[]; extern const unsigned char touch_wah_id[];