diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b5b2d15 --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ + + +SRC = $(wildcard *.cpp) +OBJ = $(subst .cpp,.o,$(SRC)) +DEP = $(subst .cpp,.d,$(SRC)) + +# The -M* switches automatically generate .d dependency files +CPPFLAGS += -MP -MMD $(INCDIRS) + +LDLIBS = -ljack -lrtmidi -lusb-1.0 + +BIN = mustang_midi + +opt: CXXFLAGS += -O3 -DNDEBUG +opt: $(BIN) + +debug: CXXFLAGS += -g -DDEBUG +debug: $(BIN) + +$(BIN): $(OBJ) + $(CXX) $^ -o $@ $(LDLIBS) + +clean: + rm -f $(DEP) $(OBJ) $(BIN) + +-include $(SRC:.cpp=.d) + diff --git a/data_structs.h b/data_structs.h new file mode 100644 index 0000000..2bdb355 --- /dev/null +++ b/data_structs.h @@ -0,0 +1,38 @@ +#ifndef DATA_STRUCTS_H +#define DATA_STRUCTS_H + +struct amp_settings +{ + unsigned char amp_num; + unsigned char gain; + unsigned char volume; + unsigned char treble; + unsigned char middle; + unsigned char bass; + unsigned char cabinet; + unsigned char noise_gate; + unsigned char master_vol; + unsigned char gain2; + unsigned char presence; + unsigned char threshold; + unsigned char depth; + unsigned char bias; + unsigned char sag; + bool brightness; + unsigned char usb_gain; +}; + +struct fx_pedal_settings +{ + unsigned char fx_slot; + unsigned char effect_num; + unsigned char knob1; + unsigned char knob2; + unsigned char knob3; + unsigned char knob4; + unsigned char knob5; + unsigned char knob6; + bool put_post_amp; +}; + +#endif // DATA_STRUCTS_H diff --git a/doc/bronco_usb_amps_effects.txt b/doc/bronco_usb_amps_effects.txt new file mode 100644 index 0000000..45ebae4 --- /dev/null +++ b/doc/bronco_usb_amps_effects.txt @@ -0,0 +1,758 @@ +Fender Bronco 40 +usb sniffed stuff + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 03|DSP| 00 | 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |mod| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 |vol|gai|ga2|mvl|tre|mid|bas|prs|?? |dep|bis|?? | number |ng | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 |ths|cab|?? |sag|bri| 01|?? | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +DSP - for amplifier it is always 5 +mod - amplifier model; different for each emulated amp +vol - volume +gai - gain +ga2 - gain 2 +mvl - master volume +tre - treble +mid - middle +bas - bass +prs - presence +dep - depth +bis - bias +number - don't know what this is; different for each emulated amp +ng - noise gate; value 0x00 - 0x05 +ths - threshold; value 0x00 - 0x09 +cab - cabinet; value 0x00 - 0x0c +sag - sag; value 0x00 - 0x02 +bri - brightness; value 0x00-0x01 +?? - values which I haven't decoded yet; different for each emulated amp + +After packet with data described above you have to send a packet which will tell the amp to actually apply the settings. This packet have zeroth byte set to "0x1c", first to "0x03" and all other to "0x00". +4. Setting and clearing effects + +Data format for setting an effect is: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 03|DSP| 00 | 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |fxm| 00|slt| ??| ??| ??| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 |kb1|kb2|kb3|kb4|kb5|kb6| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +DSP - can be either 6, 7, 8 or 9; depends on effect familly +fxm - effect model; independent for each effect +slt - slot; before amp have numbers from 0 to 3, after from 4 to 7 +kb1, kb2, kb3, kb4, kb5, kb6 - knobs values; not every time all are used; maximum + value of the knob depends on the effect +?? - some strange numbers specific for each effect + +If you want to remove the effect send normal effect-setting packet but set "effect model" and knobs fields to zeros. +I haven't tried what happens if you send such packet to DSP 0x05. +"Execute" command for both setting and clearing the effect is the same as for the amp setting. +5. Saving settings on amplifier + +Saving settings is very easy since you don't have to transmit all the settings which you want to store. You only send a command containing slot number and name for a preset. Data are taken directly from DSPs. +Packet format is: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 01| 03| 00|SLT| 00| 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 | name | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 | name | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +SLT - memory bank to which to save settings; value 0x00 - 0x17 +name - name of the preset ended with "\0"; if not all fields are used used the rest + is set to 0x00 + +Fender FUSE after saving settings chooses memory bank it just saved. PLUG also does this. +6. Choosing memory bank + +"Choose memory bank" command looks like this: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 01| 01| 00|SLT| 00| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +SLT - memory bank to choose + +--Change one Value-- + +00 05 c3 02 96 00 00 00 0c 00 ff ff 00 00 00 00 00 +10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 05| c3|dsp|mod| 00|kbn|kbn|efs| 00|vll|val| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + + +mod model of amp or effect + +dsp dsp model +02 Amps +03 StompBox +04 Mod/Filter +05 Delay +06 Reverb + +vll lower bit's of the value mostly second bit eg val:04 vll:44 val:80 vll:00 + at cabinet, noise gate,compressor its the value +val value the value of the knob + +efs Effect section +01 costom +0c mabe default of the amp +0d bias +12 mabe overdrive +8d Punch, Scoop, Limiter, ultralow knob +8f sag matched +86 Noise Gate Thresh +90 Noise Gate +93 cabinet +94 compressor + +kbn Knob number begin by 00 in order to amp data row +efs:0c +00 vol +01 gain +02 blend +03 +04 treble +05 mid +06 bass +07 Presence +08 AuralEnhacer +09 noise gate depth +1d mid frequency + +efs:01 +17 Level compressor +18 Thresh +19 Ratio +1a Attack +1b Release + +efs:0d +0a bias + +efs:12 +1c overdrive blend + +efs:8d +14 Punch, Scoop, Limiter, ultralow knob + punch vll:fe on + scoop vll:fb on + limiter vll:7f on + ultra low- vll:fd on + ultra low+ vll:fb on + punch and scoop vll:fa on + punch and limiter vll:7e on + scoop and limiter vll:7b on + punch scoop ultra low- vll:f8 on + scoop ultra low- vll:f9 on + punch ultra low- vll:fc on + punch scoop limiter vll:7a on + ulra low- punch limiter vll:7c on + +efs:8f +13 sag vll:00-02 + +efs:86 +10 noise gate thresh vll: 0-9 + +efs:90 +0f noise Gate vll: 00= 0ff 01=low 02=mid 03=high 04=super + +efs:93 +11 cabinet vll: 00= off 01=1x10modern 02=2x10modern 03=4x10modern 04=4x10 Hi-Fi + 0d=4x10vintage 05=8x10modern 06=8x10vintage 07=1x12modern 09=4x12modern + 0a=1x15vintage 0b=1x15modern 08=2x15vintage 0c=1x18vintage + +efs:94 +16 compressor vll: 00=off 01=Low1 02=Low2 03=Low3 04-06 =Mid1,2,3 + 07-09High1,2,3 0a-0c= Ultra1,2,3 + + +USB Gain + +0000 1c 03 0d 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| c3| 0d| 00| 00|kbn|kbn| 00| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |val 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +val is the volume of the usb gain 00-ff + + + + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 03|DSP| 00 | 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |fxm| 00|slt| ??| ??| ??| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 |vol|gai|ga2|mvl|tre|mid|bas|prs|?? |dep|bis|?? | number |ng | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 |ths|cab|?? |sag|bri| 01|?? | 00 00| + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f + 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f + +DSP - for amplifier it is always 5 +mod - amplifier model; different for each emulated amp +vol - volume +gai - gain +ga2 - gain 2 +mvl - master volume +tre - treble +mid - middle +bas - bass +prs - presence +dep - depth +bis - bias +number - don't know what this is; different for each emulated amp +ng - noise gate; value 0x00 - 0x05 +ths - threshold; value 0x00 - 0x09 +cab - cabinet; value 0x00 - 0x0c +sag - sag; value 0x00 - 0x02 +bri - brightness; value 0x00-0x01 +?? - values which I haven't decoded yet; different for each emulated amp + +--Amps-- +Fender Rumble + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 96 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 e6 00 80 ff 8e 71 80 80 80 80 80 80 01 01 01 01 +0030 00 03 01 01 7f 01 01 80 ff 80 80 80 55 aa 64 00 + +0-10: Gain[0] volume[9] treble[5,5] middle[4,5] mid freq [6] bass[5] +ng: Low -> treshold:0/10 deth:mid bias:mid carbinet:4x10 modern + + +Fender '59 Bassman + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 64 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 e3 47 00 80 63 aa aa 91 80 80 80 80 02 02 02 01 +0030 00 0d 02 01 7f 01 01 80 ff 80 80 80 80 80 97 00 + + +Fender Bassman TV + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 97 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 e9 aa 80 63 55 55 9c 80 80 80 80 80 03 03 03 00 +0030 00 0a 03 01 7f 01 01 80 ff 80 80 80 ff 80 98 00 + + +Fender Bassman 300 + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 c7 42 80 80 80 80 80 80 80 80 80 80 04 04 04 01 +0030 00 05 04 01 7f 01 01 80 ff 80 80 80 8e 80 99 00 + + +SWR Redhead + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 99 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 80 aa 80 ff 80 80 aa 80 63 80 80 80 05 05 05 00 +0030 00 02 05 01 7d 01 01 80 ff 80 80 80 80 80 9a 00 + + +Rockin' Peg + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 9a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 aa aa 80 ff 9c 47 9c 80 80 80 80 80 06 06 06 01 +0030 00 06 06 01 7e 01 01 80 ff 80 80 80 80 80 9b 00 + + +KGB 800 + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 9b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 f1 aa ff aa 80 80 9c 80 80 80 80 80 07 07 07 00 +0030 00 04 07 01 7b 01 01 80 ff 80 80 80 80 80 bd 00 + + +Monster + +0000 1c 03 05 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 bd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0020 e3 80 80 e3 55 47 aa 80 80 80 80 80 08 08 08 01 +0030 00 09 08 01 7f 01 01 80 ff 80 80 80 42 e3 00 00 + +--Effects-- +- +Stomp Box- + +Data format for setting an effect is: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 03|DSP| 00 | 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |fxm| 00|slt| ??| ??| ??| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 |kb1|kb2|kb3|kb4|kb5|kb6| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 1c 03 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +10 c6 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +20 55 aa aa aa 55 80 00 00 00 00 00 00 00 00 00 00 +30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +DSP: +06 Modern Bass Overdrive + +Knobs: kb1 -kb6 = 00-05 + +00 Level +01 Drive +02 Blend +04 Bass +05 Trebble +05 Presence + + + + + +MODERN OD (Overdrive) + +c6: + +Level Drive Blend Bass Treb Pres + +0000 1c 03 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c6 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 55 aa aa aa 55 80 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +0000 1c 01 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c6 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Overdrive +Level Gain Blend Low Mid High + +0000 1c 03 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c3 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 80 aa 80 80 55 55 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c3 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Fuzz +Level Gain Oktave Low High Blend + +0000 1c 03 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c4 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 53 aa 00 aa 00 55 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c4 00 00 00 08 01 01 00 00 00 00 00 00 00 00 00 +0020 ff ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Greenbox + +Level Gain Tone Blend + +0000 1c 03 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 ba 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 80 80 80 42 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 ba 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Simple Comp + +Type 00-03 + +0000 1c 03 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 88 00 00 08 08 01 00 00 00 00 00 00 00 00 00 00 +0020 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 06 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 88 00 00 08 08 01 00 00 00 00 00 00 00 00 00 00 +0020 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +--Mod/Filter-- + +Sinus Chorus + +Level Rate Depth AVG DLY LRPhase +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 12 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 05 80 05 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 12 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff ff ff ff ff 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Triangle Chourus +Level Rate Depth AVGDLY LRPhase +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 13 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 0e 19 19 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Sin Flanger +Level Rate Depth FDBack LRPhase + +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 18 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 0e 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Triangel Flanger +Level Rate Depth FDBack LRPhase +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 19 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 00 ff ff 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Vibratone +Level Rotor Death FDBack LRPhase + +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 2d 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 e3 38 27 ad 82 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Phaser +Level Rate Deph FDBack Shape +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 4f 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 11 fd 58 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 4f 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff ff ff ff 01 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Step Filter +Level Rate Resnnce MinFreq MaxFreq + +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 29 00 00 01 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Envelope +Level Mode Type Q Thresh + +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c5 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 00 01 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 c5 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 03 02 ff ff 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Oktaver +Direct Octave Sizzle + +0000 1c 03 07 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 bc 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff ff 80 00 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + +--Delay-- + +Mono +Level DLYTime FDBack Bright Attnuat +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 16 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + +Ducking +Level DLYTime DSBack Release Thresh +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 15 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 3d 6b ff 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Multitap +Level DLYTime FDBack Bright Mode +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 44 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 80 00 80 02 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +0000 1c 01 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 44 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff ff ff ff 03 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Ping Pong +Level DLYTime FDBack Bright Stereo +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 45 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Reverse +Level DLYTime FFDBK RFDBK Tone +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 46 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Tape +Level DLYTime FDBack Flutter Bright Stereo + +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 2b 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 7d 1c 00 63 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Stereo Tape +Level DLYTime FDBack Flutter Separatn Bright + +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 2a 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 7d 88 1c 63 ff 80 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Mono Echo Filter +Level DLYTime FDBack Freq Resnnce INLVL + +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 43 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 80 55 55 38 80 ff 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Stereo Echo Filter +Level DLYTime FDBack Freq Resnnce INLVL + +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 48 00 00 02 01 01 00 00 00 00 00 00 00 00 00 00 +0020 80 b3 80 38 80 ff 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Pitch Shift +Level Pitch Detune FDBack PREDly +0000 1c 03 08 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 bb 00 00 01 08 01 00 00 00 00 00 00 00 00 00 00 +0020 c7 3e 80 00 00 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + + +--Reverb-- + +Smal Hall +Level Decay DWell Diffuse Tone +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 24 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 6e 5d 6e 80 91 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Large Hall +Level Decay Dwell Diffusn Tone +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 3a 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 4f 3e 80 05 b0 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +Small Room +Level Decay Dwell Diffusn Tone +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 26 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 80 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Large Room +Level Decay Dwell Diffusn Tone +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 3b 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 80 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Small Plate +Level Decay Dwell Diffusn Tone + +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 4e 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 80 8e 1c 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +Large Plate +Level Decay Dwell Diffusn Tone +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 4b 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 38 80 91 80 b6 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + +Ambienete +Level Decay Dwell Diffusn Tone +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 4c 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + +Arena +Level Decay Dwell Diffusn Tone + +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 4d 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 ff 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + +'63 Fender Spring +Level Decay Dwell Diffusn Tone +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 21 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 80 80 80 80 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + +'65 Fender Spring +Level Decay Dwell Diffusn Tone + +0000 1c 03 09 00 00 00 01 01 00 00 00 00 00 00 00 00 +0010 0b 00 01 00 08 01 00 00 00 00 00 00 00 00 00 00 +0020 80 8b 49 ff 80 00 00 00 00 00 00 00 00 00 00 00 +0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/fender_mustang_protocol.txt b/doc/fender_mustang_protocol.txt new file mode 100644 index 0000000..2fdd454 --- /dev/null +++ b/doc/fender_mustang_protocol.txt @@ -0,0 +1,672 @@ +Technicalities + +Here I want to put all the info I have about how Mustang amp works +under the hood. + +Table of contents + + Overview + Connecting + Setting amp + Setting and clearing effects + Saving settings on amplifier + Choosing memory bank + Captured data + +1. Overview + +It has five DSPs. One for each effect family and one for amplifier +emulation. DSPs are addressed from 5 to 9. I don't know why first five +addresses are omitted and if this means anything. DSPs with their +functionality are as follows: + + 0x05 - amplifier emulation + 0x06 - stompbox effects + 0x07 - modulation effects + 0x08 - delay effects + 0x09 - reverb effects + + I also have found packets with device address 0x0a but don't know what this is. + +2. Connecting + +All the transmission between program and amplifier is using USB +interrupt transfer. Endpoint to which you want to send data is 0x01 +and USB interface which you want to claim is 0x00. If you want to +receive data from amplifier use endpoint 0x81. + +Each packet carries 64 bytes of data. + +When connecting you should send two packets to the amp and get +response for each of them. First should have value "0xc3" set on the +first position (counting from zero) and second values "0x1a" and +"0x03" on zeroth and first position. + +After that a packet asking for amp's settings is send. The packet is +of form "0xff" on zeroth and "0xc1" on first position. Amplifier +responds to that sending: + + names of all presets in the form: + + packet with name in a form: values "0x1c 0x01 0x04" as first + three bytes, then slot number on forth byte and name encoded + in ASCII on 32 bytes starting from sixteenth + + packet with two first bytes and forth (slot of the preset) the + same as in name packet + + current state of the amp in the form: + + name of the current preset in the form as described above + + amplifiers setting in the form the same as when setting + amplifier's settings (below) except that first byte is not + "0x03" but "0x01" and preset number encoded on the forth byte + + settings of four effects as described below with the same + change to the first byte as in amplifier's settings and preset + number encoded on the forth byte + + setting of some mysterious device with address "0x0a" + + confirmation packet same as in preset names + + names with settings of all presets on the Mod and Dly/Rev knobs + (first all settings for Mod knob then all settings for Dly/Rev + knob) in the form: + + name of the preset in the form: values "0x1c 0x01 0x04" as + first three bytes, value "0x01" for Mod or "0x02" for Dly/Rev + knob on third position, slot number on forth position (counted + from zero), name encoded in ASCII on 24 bytes starting from + sixteenth byte + + settings of the effect in the same form as for setting the + effect (below) except that first byte is "0x01" not "0x03" and + preset number encoded on the forth byte + + This packet is set only when sending Dly/Rev presets Dly/Rev + knob hold settings for two effects so the next packet carries + info about second effect, if effect is not set the packet have + the same form as packet for clearing effect except that first + byte is "0x01" not "0x03" and preset number encoded on the + forth byte + + confirmation packet with values "0x1c 0x01" on zeroth and + first byte, "0x01" or "0x02" depending on the knob on third + byte and preset number encoded on the forth byte + +Wireshark file with whole initialization communication can be found here. + +3. Setting amp + +Format of data for setting amp is as follow: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 03|DSP| 00 | 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |mod| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 |vol|gai|ga2|mvl|tre|mid|bas|prs|?? |dep|bis|?? | number |ng | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 |ths|cab|?? |sag|bri| 01|?? | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +DSP - for amplifier it is always 5 +mod - amplifier model; different for each emulated amp +vol - volume +gai - gain +ga2 - gain 2 +mvl - master volume +tre - treble +mid - middle +bas - bass +prs - presence +dep - depth +bis - bias +number - don't know what this is; different for each emulated amp +ng - noise gate; value 0x00 - 0x05 +ths - threshold; value 0x00 - 0x09 +cab - cabinet; value 0x00 - 0x0c +sag - sag; value 0x00 - 0x02 +bri - brightness; value 0x00-0x01 +?? - values which I haven't decoded yet; different for each emulated amp + +After packet with data described above you have to send a packet which +will tell the amp to actually apply the settings. This packet have +zeroth byte set to "0x1c", first to "0x03" and all other to "0x00". + +4. Setting and clearing effects + +Data format for setting an effect is: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 03|DSP| 00 | 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |fxm| 00|slt| ??| ??| ??| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 |kb1|kb2|kb3|kb4|kb5|kb6| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +DSP - can be either 6, 7, 8 or 9; depends on effect familly +fxm - effect model; independent for each effect +slt - slot; before amp have numbers from 0 to 3, after from 4 to 7 + kb1, kb2, kb3, kb4, kb5, kb6 - knobs values; not every time + all are used; maximum value of the knob depends on the effect +?? - some strange numbers specific for each effect + +If you want to remove the effect send normal effect-setting packet but +set "effect model" and knobs fields to zeros. I haven't tried what +happens if you send such packet to DSP 0x05. + +"Execute" command for both setting and clearing the effect is the same +as for the amp setting. + +5. Saving settings on amplifier + +Saving settings is very easy since you don't have to transmit all the +settings which you want to store. You only send a command containing +slot number and name for a preset. Data are taken directly from DSPs. + +Packet format is: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 01| 03| 00|SLT| 00| 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 | name | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 | name | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +SLT - memory bank to which to save settings; value 0x00 - 0x17 + +name - name of the preset ended with "\0"; if not all fields are used + used the rest is set to 0x00 + +Fender FUSE after saving settings chooses memory bank it just +saved. PLUG also does this. + +6. Choosing memory bank + +"Choose memory bank" command looks like this: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 01| 01| 00|SLT| 00| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +SLT - memory bank to choose + +After choosing memory bank amplifier send you settings of that bank. + +7. Captured data + +Wireshark file with whole initialization communication can be found +here: http://piorekf.org/plug/files/initialization.log And here are +data from captured packets for setting all the amps and effects (only +hex part, the rest are my scribbles): + +AMPLIFIERS: + +fender 57 deluxe: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +67:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:99:80:80:be:80:80:80 80:80:80:80:01:01:01:00 +00:01:01:01:00:01:53:00 00:00:00:00:00:00:00:00 +0-10: gain[6] volume[7] treble[7.5] middle[5] bass[5] +NG: off -> threshold: 0/10 depth: mid sag: 2/3 bias: mid cabinet: 57dlx + +fender 59 bassman: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +64:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:a2:80:80:80:7a:a2:91 80:80:80:80:02:02:02:00 +00:02:02:01:00:01:67:00 00:00:00:00:00:00:00:00 +0-10: gain[6.5] volume[7] treble[5] middle[~5] bass[6.5] presence[~6] + +blend: mid NG: off -> threshold: 0/10 depth: mid sag: 2/3 bias: mid +cabinet: bssmn + +fender 57 champ: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +7c:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:b3:00:ff:80:80:80:80 80:80:80:80:0c:0c:0c:00 +00:05:0c:01:00:01:00:00 00:00:00:00:00:00:00:00 +0-10: gain[7] volume[~7] treble[5] middle[5] bass[5] +NG: off -> threshold: 0/10 depth: mid sag: 2/3 bias: mid cabinet: champ + +fender 65 deluxe reverb: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +53:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:71:00:ff:91:cf:38:00 00:00:80:00:03:03:03:00 +00:03:03:01:00:01:6a:00 00:00:00:00:00:00:00:00 + +1-10: gain[5] volume[7] treble[6.25] middle[8.75] bass[3] -reverb[~1] +-speed[7] -intensivity[9] + +NG: off -> threshold: 0/10 depth: 0 sag: 2/3 bias: mid cabinet: 65dlx + +fender 65 princeton: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +6a:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:55:00:ff:99:cc:4c:80 80:80:80:80:04:04:04:00 +00:04:04:01:00:01:61:00 00:00:00:00:00:00:00:00 + +1-10: gain[4] volume[7] treble[6.5] middle[8.5] bass[4] -reverb[5.5] +-speed[7] -intensivity[9] + +NG: off -> threshold: 0/10 depth: mid sag: 2/3 bias: mid cabinet: +65prn + +fender 65 twin reverb: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +75:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:55:80:63:b3:bb:aa:80 80:80:80:80:05:05:05:00 +00:09:05:01:00:01:72:00 00:00:00:00:00:00:00:00 + +1-10: +bright gain[4] volume[7] treble[7.5] middle[8] bass[7] +-reverb[5.5] -speed[7] -intensivity[9] + +NG: off -> threshold: 0/10 depth: mid sag: 2/3 bias: mid cabinet: +65twn + +fender super sonic: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +72:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:bb:82:55:99:a2:99:80 80:80:80:80:06:06:06:02 +00:0c:06:01:00:01:79:00 00:00:00:00:00:00:00:00 + +1-10: gain[7.5] gain2[5.5] volume[7] treble[6.5] middle[7] bass[6.5] +-reverb[5.5] + +master vol: 33% NG: mid -> threshold: 0/10 depth: mid sag: 2/3 bias: +mid cabinet: ss112 + +british 60s: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +61:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:a2:80:63:99:80:b0:00 80:80:80:80:07:07:07:00 +00:07:07:01:00:01:5e:00 00:00:00:00:00:00:00:00 + +0-10: +bright gain[6.5] volume[7] treble[6] middle[5] bass[7] +-speed[7] -depth[8.75] cut[0] + +NG: off -> threshold: 0/10 depth: mid sag: 2/3 bias: mid cabinet: +2x12c + +british 70s: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +79:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:ff:80:7d:aa:5b:c4:80 80:80:80:80:0b:0b:0b:01 +00:08:0b:01:00:01:7c:00 00:00:00:00:00:00:00:00 + +0-10: gain[10] volume[7] treble[7] middle[3] bass[8] presence[5] + +blend: mid NG: low -> threshold: 0/10 depth: mid sag: 2/3 bias: mid +cabinet: 4x12g + +british 80s: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +5e:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:ff:80:7d:aa:5b:c4:80 80:80:80:80:09:09:09:01 +00:06:09:01:00:01:5d:00 00:00:00:00:00:00:00:00 + +0-10: gain[10] volume[7] treble[7] middle[3] bass[8] presence[5] + +master vol: 50% NG: low -> threshold: 0/10 depth: mid sag: 2/3 bias: +mid cabinet: 4x12m + +american 90s: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +5d:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:8e:80:66:a4:19:c7:71 80:80:80:80:0a:0a:0a:03 +00:0a:0a:01:00:01:6d:00 00:00:00:00:00:00:00:00 + +?1-10?: gain[~1/2] volume[2/3] treble[2/3] middle[~1/10] bass[3/4] +presence[~1/2] + +master vol: 33% NG: high -> threshold: 0/10 depth: mid sag: 2/3 bias: +mid cabinet: 4x12v + +metal 2000: +1c:03:05:00:00:00:01:01 00:00:00:00:00:00:00:00 +6d:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +aa:a4:80:55:99:4c:91:8e 80:80:80:80:08:08:08:02 +00:08:08:01:00:01:75:00 00:00:00:00:00:00:00:00 + +0-10: gain[6.5] volume[7] treble[6] middle[3] bass[6] presence[5.5] + +master vol: 33% NG: mid -> threshold: 0/10 depth: mid sag: 2/3 bias: +mid cabinet: 4x12g + + + +EFFECTS: + +overdrive: +1c:03:06:00:00:00:01:01 00:00:00:00:00:00:00:00 +3c:00:03:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level gain low mid high + +fixed wah: +1c:03:06:00:00:00:01:01 00:00:00:00:00:00:00:00 +49:00:03:01:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level frequency min frequency max frequency q + +touch wah: +1c:03:06:00:00:00:01:01 00:00:00:00:00:00:00:00 +4a:00:03:01:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level sensivity min frequency max frequency q + +fuzz: +1c:03:06:00:00:00:01:01 00:00:00:00:00:00:00:00 +1a:00:03:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level gain octave low high + +fuzz touch wah: +1c:03:06:00:00:00:01:01 00:00:00:00:00:00:00:00 +1c:00:03:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level gain sensivity octave peak + +simple comp (1 knob): +1c:03:06:00:00:00:01:01 00:00:00:00:00:00:00:00 +88:00:03:08:08:01:00:00 00:00:00:00:00:00:00:00 +01:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +type[0-3] + +compressor: +1c:03:06:00:00:00:01:01 00:00:00:00:00:00:00:00 +07:00:03:00:08:01:00:00 00:00:00:00:00:00:00:00 +8d:0f:4f:7f:7f:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level threshhold ratio attack release + + + +sine chorus: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +12:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +ff:0e:19:19:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate depth average delay lr phase + +triangle chorus: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +13:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +5d:0e:19:19:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate depth average delay lr phase + +sine flanger: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +18:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +ff:0e:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate depth feedback lr phase + +triangle flanger: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +19:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +ff:00:ff:33:41:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate depth feedback lr phase + +vibratone: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +2d:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +f4:ff:27:ad:82:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rotor depth feedback lr phase + +vintage tremolo: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +40:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +db:ad:63:f4:f1:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate duty cycle attack release + +sine tremolo: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +41:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +db:99:7d:00:00:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate duty cycle lfo clipping tri shaping + +ring modulator: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +22:00:02:01:08:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level frequency depth lfo shape[0-1] lfo phase + +step filter: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +29:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate resonance min frequency max frequency + +phaser: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +4f:00:02:01:01:01:00:00 00:00:00:00:00:00:00:00 +fd:00:fd:b8:00:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level rate depth feedback lfo shape[0-1] + +pitch shifter: +1c:03:07:00:00:00:01:01 00:00:00:00:00:00:00:00 +1f:00:02:01:08:01:00:00 00:00:00:00:00:00:00:00 +c7:3e:80:00:00:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level pitch detune feedback predelay + + + +mono delay: +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +16:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback brightness attenuation + +mono echo filter (6 knobs): +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +43:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:80:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback frequency ressonance input level + +stereo echo filter (6 knobs): +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +48:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +80:b3:80:80:80:80:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback frequency ressonance input level + +multitap delay: +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +44:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +ff:80:66:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback brightness attenuation + +ping pong delay: +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +45:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback brightness attenuation + +ducking delay: +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +15:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback release threshold + +reverse delay: +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +46:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback brightness attenuation + +tape delay (6 knobs): +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +2b:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +7d:1c:00:63:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback flutter brightness stereo + +stereo tape delay (6 knobs): +1c:03:08:00:00:00:01:01 00:00:00:00:00:00:00:00 +2a:00:02:02:01:01:00:00 00:00:00:00:00:00:00:00 +7d:88:1c:63:ff:80:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level delay time feedback flutter separation brightness + + + +small hall reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +24:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +6e:5d:6e:80:91:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +large hall reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +3a:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +4f:3e:80:05:b0:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +small room reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +26:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +large room reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +3b:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +small plate reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +4e:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +large plate reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +4b:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +38:80:91:80:b6:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +ambient reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +4c:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +arena reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +4d:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +ff:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +'63 fender spring reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +21:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:80:80:80:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +'65 fender spring reverb: +1c:03:09:00:00:00:01:01 00:00:00:00:00:00:00:00 +0b:00:02:00:08:01:00:00 00:00:00:00:00:00:00:00 +80:8b:49:ff:80:00:00:00 00:00:00:00:00:00:00:00 +00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 +level decay dwell diffusion tone + +====================================================================== + +Toggling effect on/off: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 19| c3|DSP| st|slt| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +DSP - can be either 6, 7, 8 or 9; depends on effect familly +st - status (on = 00, off = 01) +slt - slot; before amp have numbers from 0 to 3, after from 4 to 7 + + +1st data packet resported after toggling an effect on or off is: + + 0 1 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +00 | 1c| 01|DSP| 00 | 01| 01| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +16 |fxm| 00|slt| ??| ??| ??| 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +32 |kb1|kb2|kb3|kb4|kb5|kb6|st | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ +48 | ? | ? | ? | ? | ? | 00 | + +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ + +DSP - can be either 6, 7, 8 or 9; depends on effect familly +fxm - effect model; independent for each effect +slt - slot; before amp have numbers from 0 to 3, after from 4 to 7 + +kb1, kb2, kb3, kb4, kb5, kb6 - knobs values; not every time + all are used; maximum value of the knob depends on the effect + +st - Status (on = 00, off = 01) + +This is followed by two more packets whose purpose is unknown. + diff --git a/effects_enum.h b/effects_enum.h new file mode 100644 index 0000000..c70d99b --- /dev/null +++ b/effects_enum.h @@ -0,0 +1,102 @@ +#ifndef EFFECTS_ENUM_H +#define EFFECTS_ENUM_H + +// enums used for switches (looks nicer +// and is more practical than numbers) + +// list of all amplifiers +enum amps +{ + STUDIO_PREAMP, + FENDER_57_CHAMP, + FENDER_57_DELUXE, + FENDER_57_TWIN, + FENDER_59_BASSMAN, + FENDER_65_PRINCETON, + FENDER_65_DELUXE_REVERB, + FENDER_65_TWIN_REVERB, + S60S_THRIFT, + BRITISH_WATTS, + BRITISH_60S, + BRITISH_70S, + BRITISH_80S, + BRITISH_COLOUR, + FENDER_SUPER_SONIC, + AMERICAN_90S, + METAL_2000 + +}; + +// list of all effects +enum effects +{ + EMPTY, + RANGER, + GREENBOX, + OVERDRIVE, + FUZZ, + ORANGEBOX, + BLACKBOX, + BIG_FUZZ, + WAH, + TOUCH_WAH, + FUZZ_TOUCH_WAH, + SIMPLE_COMP, + COMPRESSOR, + + SINE_CHORUS, + TRIANGLE_CHORUS, + SINE_FLANGER, + TRIANGLE_FLANGER, + VIBRATONE, + VINTAGE_TREMOLO, + SINE_TREMOLO, + RING_MODULATOR, + STEP_FILTER, + PHASER, + MOD_WAH, + MOD_TOUCH_WAH, + DIATONIC_PITCH_SHIFTER, + PITCH_SHIFTER, + + MONO_DELAY, + MONO_ECHO_FILTER, + STEREO_ECHO_FILTER, + MULTITAP_DELAY, + PING_PONG_DELAY, + DUCKING_DELAY, + REVERSE_DELAY, + TAPE_DELAY, + STEREO_TAPE_DELAY, + + SMALL_HALL_REVERB, + LARGE_HALL_REVERB, + SMALL_ROOM_REVERB, + LARGE_ROOM_REVERB, + SMALL_PLATE_REVERB, + LARGE_PLATE_REVERB, + AMBIENT_REVERB, + ARENA_REVERB, + FENDER_63_SPRING_REVERB, + FENDER_65_SPRING_REVERB +}; + +// list of all cabinets +enum cabinets +{ + OFF, + cab57DLX, + cabBSSMN, + cab65DLX, + cab65PRN, + cabCHAMP, + cab4x12M, + cab2x12C, + cab4x12G, + cab65TWN, + cab4x12V, + cabSS212, + cabSS112 +}; + +#endif // EFFECTS_ENUM_H diff --git a/mustang.cpp b/mustang.cpp new file mode 100644 index 0000000..5f0d1c6 --- /dev/null +++ b/mustang.cpp @@ -0,0 +1,1502 @@ +#include "mustang.h" +#include + +Mustang::Mustang() +{ + amp_hand = NULL; + + // "apply efect" command + memset(execute, 0x00, LENGTH); + execute[0] = 0x1c; + execute[1] = 0x03; + + memset(prev_array, 0x00, LENGTH*4); + for(int i = 0; i < 4; i++) + { + prev_array[i][0] = 0x1c; + prev_array[i][1] = 0x03; + prev_array[i][6] = prev_array[i][7] = prev_array[i][21] = 0x01; + prev_array[i][20] = 0x08; + prev_array[i][FXSLOT] = 0xff; + } +} + +Mustang::~Mustang() +{ + this->stop_amp(); +} + +int Mustang::start_amp(char list[][32], char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) +{ + int ret, received; + unsigned char array[LENGTH]; + unsigned char received_data[296][LENGTH], data[7][LENGTH]; + memset(received_data, 0x00, 296*LENGTH); + + if(amp_hand == NULL) + { + // initialize libusb + ret = libusb_init(NULL); + if (ret) + return ret; + + // get handle for the device + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, OLD_USB_PID)) == NULL) + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, NEW_USB_PID)) == NULL) + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, V2_USB_PID)) == NULL) + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, MINI_USB_PID)) == NULL) + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, FLOOR_USB_PID)) == NULL) + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, BRONCO40_USB_PID)) == NULL) + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, V2_III_PID)) == NULL) + if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, V2_IV_PID)) == NULL) + { + libusb_exit(NULL); + return -100; + } + + // detach kernel driver + ret = libusb_kernel_driver_active(amp_hand, 0); + if(ret) + { + ret = libusb_detach_kernel_driver(amp_hand, 0); + if(ret) + { + stop_amp(); + return ret; + } + } + + // claim the device + ret = libusb_claim_interface(amp_hand, 0); + if(ret) + { + stop_amp(); + return ret; + } + } + + // initialization which is needed if you want + // to get any replies from the amp in the future + memset(array, 0x00, LENGTH); + array[1] = 0xc3; + libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + memset(array, 0x00, LENGTH); + array[0] = 0x1a; + array[1] = 0x03; + libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + if(list != NULL || name != NULL || amp_set != NULL || effects_set != NULL) + { + int i = 0, j = 0; + memset(array, 0x00, LENGTH); + array[0] = 0xff; + array[1] = 0xc1; + libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + + for(i = 0; received; i++) + { + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + memcpy(received_data[i], array, LENGTH); + } + + int max_to_receive; + i > 143 ? max_to_receive = 200 : max_to_receive = 48; + if(list != NULL) + for(i = 0, j = 0; i 0x03) + { + array[KNOB1] = 0x03; + } + array[KNOB2] = 0x00; + array[KNOB3] = 0x00; + array[KNOB4] = 0x00; + array[KNOB5] = 0x00; + break; + + case COMPRESSOR: + array[DSP] = 0x06; + array[EFFECT] = 0x07; + break; + + case SINE_CHORUS: + array[DSP] = 0x07; + array[EFFECT] = 0x12; + array[19] = 0x01; + array[20] = 0x01; + break; + + case TRIANGLE_CHORUS: + array[DSP] = 0x07; + array[EFFECT] = 0x13; + array[19] = 0x01; + array[20] = 0x01; + break; + + case SINE_FLANGER: + array[DSP] = 0x07; + array[EFFECT] = 0x18; + array[19] = 0x01; + array[20] = 0x01; + break; + + case TRIANGLE_FLANGER: + array[DSP] = 0x07; + array[EFFECT] = 0x19; + array[19] = 0x01; + array[20] = 0x01; + break; + + case VIBRATONE: + array[DSP] = 0x07; + array[EFFECT] = 0x2d; + array[19] = 0x01; + array[20] = 0x01; + break; + + case VINTAGE_TREMOLO: + array[DSP] = 0x07; + array[EFFECT] = 0x40; + array[19] = 0x01; + array[20] = 0x01; + break; + + case SINE_TREMOLO: + array[DSP] = 0x07; + array[EFFECT] = 0x41; + array[19] = 0x01; + array[20] = 0x01; + break; + + case RING_MODULATOR: + array[DSP] = 0x07; + array[EFFECT] = 0x22; + array[19] = 0x01; + if(array[KNOB4] > 0x01) + { + array[KNOB4] = 0x01; + } + break; + + case STEP_FILTER: + array[DSP] = 0x07; + array[EFFECT] = 0x29; + array[19] = 0x01; + array[20] = 0x01; + break; + + case PHASER: + array[DSP] = 0x07; + array[EFFECT] = 0x4f; + array[19] = 0x01; + array[20] = 0x01; + if(array[KNOB5] > 0x01) + { + array[KNOB5] = 0x01; + } + break; + + case PITCH_SHIFTER: + array[DSP] = 0x07; + array[EFFECT] = 0x1f; + array[19] = 0x01; + break; + + case MONO_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x16; + array[19] = 0x02; + array[20] = 0x01; + break; + + case MONO_ECHO_FILTER: + array[DSP] = 0x08; + array[EFFECT] = 0x43; + array[19] = 0x02; + array[20] = 0x01; + break; + + case STEREO_ECHO_FILTER: + array[DSP] = 0x08; + array[EFFECT] = 0x48; + array[19] = 0x02; + array[20] = 0x01; + break; + + case MULTITAP_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x44; + array[19] = 0x02; + array[20] = 0x01; + if(array[KNOB5] > 0x03) + { + array[KNOB5] = 0x03; + } + break; + + case PING_PONG_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x45; + array[19] = 0x02; + array[20] = 0x01; + break; + + case DUCKING_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x15; + array[19] = 0x02; + array[20] = 0x01; + break; + + case REVERSE_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x46; + array[19] = 0x02; + array[20] = 0x01; + break; + + case TAPE_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x2b; + array[19] = 0x02; + array[20] = 0x01; + break; + + case STEREO_TAPE_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x2a; + array[19] = 0x02; + array[20] = 0x01; + break; + + case SMALL_HALL_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x24; + break; + + case LARGE_HALL_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x3a; + break; + + case SMALL_ROOM_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x26; + break; + + case LARGE_ROOM_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x3b; + break; + + case SMALL_PLATE_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4e; + break; + + case LARGE_PLATE_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4b; + break; + + case AMBIENT_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4c; + break; + + case ARENA_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4d; + break; + + case FENDER_63_SPRING_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x21; + break; + + case FENDER_65_SPRING_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x0b; + break; + } + + // send packet to the amp + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); + ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); + //DEBUG +// qDebug("set: DSP: %d, slot: %d, effect: %d", array[DSP], array[FXSLOT], array[EFFECT]); + + // save current settings + memcpy(prev_array[array[DSP]-6], array, LENGTH); + + + //DEBUG +// FILE *f; +// static char trynum=0; +// char mes[16]; +// sprintf(mes, "test%d.bin",trynum); +// f=fopen(mes,"w"); +// fwrite(array, sizeof(array), 1, f); +// //fwrite(execute, sizeof(execute), 1, f); +// fclose(f); +// trynum++; + + + return ret; +} + +int Mustang::effect_toggle(int category, int state) +{ + int ret, received; + unsigned char array[LENGTH]; + + memset(array, 0x00, LENGTH); + array[0] = 0x19; + array[1] = 0xc3; + // Translate DSP to internal effect category + array[2] = prev_array[category][DSP] - 3; + array[3] = state; + array[FXSLOT] = prev_array[category][FXSLOT]; + + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + // flush reply data + for (int i=0; received; i++) { + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + } + + return ret; +} + + +int Mustang::set_amplifier(struct amp_settings value) +{ + int ret, received; + unsigned char array[LENGTH] = { + 0x1c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xaa, 0xa2, 0x80, 0x63, 0x99, 0x80, 0xb0, 0x00, + 0x80, 0x80, 0x80, 0x80, 0x07, 0x07, 0x07, 0x05, + 0x00, 0x07, 0x07, 0x01, 0x00, 0x01, 0x5e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + array[DSP] = 0x05; + array[GAIN] = value.gain; + array[VOLUME] = value.volume; + array[TREBLE] = value.treble; + array[MIDDLE] = value.middle; + array[BASS] = value.bass; + + if(value.cabinet > 0x0c) + array[CABINET] = 0x00; + else + array[CABINET] = value.cabinet; + + if(value.noise_gate > 0x05) + array[NOISE_GATE] = 0x00; + else + array[NOISE_GATE] = value.noise_gate; + + array[MASTER_VOL] = value.master_vol; + array[GAIN2] = value.gain2; + array[PRESENCE] = value.presence; + + if(value.noise_gate == 0x05) + { + if(value.threshold > 0x09) + array[THRESHOLD] = 0x00; + else + array[THRESHOLD] = value.threshold; + + array[DEPTH] = value.depth; + } + array[BIAS] = value.bias; + + if(value.sag > 0x02) + array[SAG] = 0x01; + else + array[SAG] = value.sag; + + array[BRIGHTNESS] = value.brightness?1:0; + + switch (value.amp_num) + { + case STUDIO_PREAMP: + array[AMPLIFIER] = 0xf1; + array[44] = array[45] = array[46] = 0x0d; + array[50] = 0x0d; + array[54] = 0xf6; + break; + + case FENDER_57_CHAMP: + array[AMPLIFIER] = 0x7c; + array[44] = array[45] = array[46] = 0x0c; + array[50] = 0x0c; + array[54] = 0x00; + break; + + case FENDER_57_DELUXE: + array[AMPLIFIER] = 0x67; + array[44] = array[45] = array[46] = 0x01; + array[50] = 0x01; + array[54] = 0x53; + break; + + case FENDER_57_TWIN: + array[AMPLIFIER] = 0xf6; + array[44] = array[45] = array[46] = 0x0e; + array[50] = 0x0e; + array[54] = 0xf9; + break; + + case FENDER_59_BASSMAN: + array[AMPLIFIER] = 0x64; + array[44] = array[45] = array[46] = 0x02; + array[50] = 0x02; + array[54] = 0x67; + break; + + case FENDER_65_PRINCETON: + array[AMPLIFIER] = 0x6a; + array[44] = array[45] = array[46] = 0x04; + array[50] = 0x04; + array[54] = 0x61; + break; + + case FENDER_65_DELUXE_REVERB: + array[AMPLIFIER] = 0x53; + array[40] = array[43] = 0x00; + array[44] = array[45] = array[46] = 0x03; + array[50] = 0x03; + array[54] = 0x6a; + break; + + case FENDER_65_TWIN_REVERB: + array[AMPLIFIER] = 0x75; + array[44] = array[45] = array[46] = 0x05; + array[50] = 0x05; + array[54] = 0x72; + break; + + case S60S_THRIFT: + array[AMPLIFIER] = 0xf9; + array[44] = array[45] = array[46] = 0x0f; + array[50] = 0x0f; + array[54] = 0xfc; + break; + + case BRITISH_WATTS: + array[AMPLIFIER] = 0xff; + array[44] = array[45] = array[46] = 0x11; + array[50] = 0x11; + array[54] = 0x00; + break; + + case BRITISH_60S: + array[AMPLIFIER] = 0x61; + array[44] = array[45] = array[46] = 0x07; + array[50] = 0x07; + array[54] = 0x5e; + break; + + case BRITISH_70S: + array[AMPLIFIER] = 0x79; + array[44] = array[45] = array[46] = 0x0b; + array[50] = 0x0b; + array[54] = 0x7c; + break; + + case BRITISH_80S: + array[AMPLIFIER] = 0x5e; + array[44] = array[45] = array[46] = 0x09; + array[50] = 0x09; + array[54] = 0x5d; + break; + case BRITISH_COLOUR: + array[AMPLIFIER] = 0xfc; + array[44] = array[45] = array[46] = 0x10; + array[50] = 0x10; + array[54] = 0xff; + break; + + case FENDER_SUPER_SONIC: + array[AMPLIFIER] = 0x72; + array[44] = array[45] = array[46] = 0x06; + array[50] = 0x06; + array[54] = 0x79; + break; + + case AMERICAN_90S: + array[AMPLIFIER] = 0x5d; + array[44] = array[45] = array[46] = 0x0a; + array[50] = 0x0a; + array[54] = 0x6d; + break; + + case METAL_2000: + array[AMPLIFIER] = 0x6d; + array[44] = array[45] = array[46] = 0x08; + array[50] = 0x08; + array[54] = 0x75; + break; + + + } + + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + memset(array, 0x00, LENGTH); + array[0] = 0x1c; + array[1] = 0x03; + array[2] = 0x0d; + array[6] = 0x01; + array[7] = 0x01; + array[16] = value.usb_gain; + + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + return ret; +} + +int Mustang::save_on_amp(char *name, int slot) +{ + int ret, received; + unsigned char array[LENGTH]; + + memset(array, 0x00, LENGTH); + array[0] = 0x1c; + array[1] = 0x01; + array[2] = 0x03; + array[SAVE_SLOT] = slot; + array[6] = 0x01; + array[7] = 0x01; + + if(strlen(name) > 31) + name[31] = 0x00; + + for(unsigned int i = 16, j = 0; name[j] != 0x00; i++,j++) + array[i] = name[j]; + + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + load_memory_bank(slot, NULL, NULL, NULL); + + return ret; +} + +int Mustang::load_memory_bank(int slot, char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) +{ + int ret, received; + unsigned char array[LENGTH], data[7][LENGTH]; + + memset(array, 0x00, LENGTH); + array[0] = 0x1c; + array[1] = 0x01; + array[2] = 0x01; + array[SAVE_SLOT] = slot; + array[6] = 0x01; + + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + + for(int i = 0; received; i++) { + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + if(i < 7) + memcpy(data[i], array, LENGTH); + } + + if(name != NULL || amp_set != NULL || effects_set != NULL) + decode_data(data, name, amp_set, effects_set); + + return ret; +} + +int Mustang::decode_data(unsigned char data[6][LENGTH], char *name, struct amp_settings *amp_set, struct fx_pedal_settings *effects_set) +{ + if(name != NULL) + { + // NAME + memset(name, 0x00, 32); + for(int i = 0, j = 16; data[0][j] != 0x00; i++, j++) + name[i] = data[0][j]; + } + + + if(amp_set != NULL) + { + // AMPLIFIER + switch(data[1][AMPLIFIER]) + { + case 0xf1: + amp_set->amp_num = STUDIO_PREAMP; + break; + + case 0x7c: + amp_set->amp_num = FENDER_57_CHAMP; + break; + + case 0x67: + amp_set->amp_num = FENDER_57_DELUXE; + break; + + case 0xf6: + amp_set->amp_num = FENDER_57_TWIN; + break; + + case 0x64: + amp_set->amp_num = FENDER_59_BASSMAN; + break; + + case 0x6a: + amp_set->amp_num = FENDER_65_PRINCETON; + break; + + case 0x53: + amp_set->amp_num = FENDER_65_DELUXE_REVERB; + break; + + case 0x75: + amp_set->amp_num = FENDER_65_TWIN_REVERB; + break; + + case 0xf9: + amp_set->amp_num = S60S_THRIFT; + break; + + case 0xff: + amp_set->amp_num = BRITISH_WATTS; + break; + + case 0x61: + amp_set->amp_num = BRITISH_60S; + break; + + case 0x79: + amp_set->amp_num = BRITISH_70S; + break; + + case 0x5e: + amp_set->amp_num = BRITISH_80S; + break; + + case 0xfc: + amp_set->amp_num = BRITISH_COLOUR; + break; + + case 0x72: + amp_set->amp_num = FENDER_SUPER_SONIC; + break; + + case 0x5d: + amp_set->amp_num = AMERICAN_90S; + break; + + case 0x6d: + amp_set->amp_num = METAL_2000; + break; + + default: + amp_set->amp_num = STUDIO_PREAMP; + break; + } + // STUDIO_PREAMP, + // FENDER_57_CHAMP, + // FENDER_57_DELUXE, + // FENDER_57_TWIN, + // FENDER_59_BASSMAN, + // FENDER_65_PRINCETON, + // FENDER_65_DELUXE_REVERB, + // FENDER_65_TWIN_REVERB, + // S60S_THRIFT, + // BRITISH_WATTS, + // BRITISH_60S, + // BRITISH_70S, + // BRITISH_80S, + // BRITISH_COLOUR, + // FENDER_SUPER_SONIC, + // AMERICAN_90S, + // METAL_2000 + + amp_set->gain = data[1][GAIN]; + amp_set->volume = data[1][VOLUME]; + amp_set->treble = data[1][TREBLE]; + amp_set->middle = data[1][MIDDLE]; + amp_set->bass = data[1][BASS]; + amp_set->cabinet = data[1][CABINET]; + amp_set->noise_gate = data[1][NOISE_GATE]; + amp_set->master_vol = data[1][MASTER_VOL]; + amp_set->gain2 = data[1][GAIN2]; + amp_set->presence = data[1][PRESENCE]; + amp_set->threshold = data[1][THRESHOLD]; + amp_set->depth = data[1][DEPTH]; + amp_set->bias = data[1][BIAS]; + amp_set->sag = data[1][SAG]; + amp_set->brightness = data[1][BRIGHTNESS]?true:false; + amp_set->usb_gain = data[6][16]; + } + + + if(effects_set != NULL) + { + // EFFECTS + for(int i = 2; i < 6; i++) + { + int j=0; + + prev_array[data[i][DSP]-6][0] = 0x1c; + prev_array[data[i][DSP]-6][1] = 0x03; + prev_array[data[i][DSP]-6][FXSLOT] = data[i][FXSLOT]; + prev_array[data[i][DSP]-6][DSP] = data[i][DSP]; + prev_array[data[i][DSP]-6][19] = data[i][19]; + prev_array[data[i][DSP]-6][20] = data[i][20]; + + switch(data[i][FXSLOT]) + { + case 0x00: + case 0x04: + j = 0; + break; + + case 0x01: + case 0x05: + j = 1; + break; + + case 0x02: + case 0x06: + j = 2; + break; + + case 0x03: + case 0x07: + j = 3; + break; + + default: + j=0; + break; + } + + effects_set[j].fx_slot = j; + effects_set[j].knob1 = data[i][KNOB1]; + effects_set[j].knob2 = data[i][KNOB2]; + effects_set[j].knob3 = data[i][KNOB3]; + effects_set[j].knob4 = data[i][KNOB4]; + effects_set[j].knob5 = data[i][KNOB5]; + effects_set[j].knob6 = data[i][KNOB6]; + if(data[i][FXSLOT] > 0x03) + effects_set[j].put_post_amp = true; + else + effects_set[j].put_post_amp = false; + + switch(data[i][EFFECT]) + { + case 0x00: + effects_set[j].effect_num = EMPTY; + break; + + case 0x3c: + effects_set[j].effect_num = OVERDRIVE; + break; + + case 0x49: + effects_set[j].effect_num = WAH; + break; + + case 0x4a: + effects_set[j].effect_num = TOUCH_WAH; + break; + + case 0x1a: + effects_set[j].effect_num = FUZZ; + break; + + case 0x1c: + effects_set[j].effect_num = FUZZ_TOUCH_WAH; + break; + + case 0x88: + effects_set[j].effect_num = SIMPLE_COMP; + break; + + case 0x07: + effects_set[j].effect_num = COMPRESSOR; + break; + + case 0x12: + effects_set[j].effect_num = SINE_CHORUS; + break; + + case 0x13: + effects_set[j].effect_num = TRIANGLE_CHORUS; + break; + + case 0x18: + effects_set[j].effect_num = SINE_FLANGER; + break; + + case 0x19: + effects_set[j].effect_num = TRIANGLE_FLANGER; + break; + + case 0x2d: + effects_set[j].effect_num = VIBRATONE; + break; + + case 0x40: + effects_set[j].effect_num = VINTAGE_TREMOLO; + break; + + case 0x41: + effects_set[j].effect_num = SINE_TREMOLO; + break; + + case 0x22: + effects_set[j].effect_num = RING_MODULATOR; + break; + + case 0x29: + effects_set[j].effect_num = STEP_FILTER; + break; + + case 0x4f: + effects_set[j].effect_num = PHASER; + break; + + case 0x1f: + effects_set[j].effect_num = PITCH_SHIFTER; + break; + + case 0x16: + effects_set[j].effect_num = MONO_DELAY; + break; + + case 0x43: + effects_set[j].effect_num = MONO_ECHO_FILTER; + break; + + case 0x48: + effects_set[j].effect_num = STEREO_ECHO_FILTER; + break; + + case 0x44: + effects_set[j].effect_num = MULTITAP_DELAY; + break; + + case 0x45: + effects_set[j].effect_num = PING_PONG_DELAY; + break; + + case 0x15: + effects_set[j].effect_num = DUCKING_DELAY; + break; + + case 0x46: + effects_set[j].effect_num = REVERSE_DELAY; + break; + + case 0x2b: + effects_set[j].effect_num = TAPE_DELAY; + break; + + case 0x2a: + effects_set[j].effect_num = STEREO_TAPE_DELAY; + break; + + case 0x24: + effects_set[j].effect_num = SMALL_HALL_REVERB; + break; + + case 0x3a: + effects_set[j].effect_num = LARGE_HALL_REVERB; + break; + + case 0x26: + effects_set[j].effect_num = SMALL_ROOM_REVERB; + break; + + case 0x3b: + effects_set[j].effect_num = LARGE_ROOM_REVERB; + break; + + case 0x4e: + effects_set[j].effect_num = SMALL_PLATE_REVERB; + break; + + case 0x4b: + effects_set[j].effect_num = LARGE_PLATE_REVERB; + break; + + case 0x4c: + effects_set[j].effect_num = AMBIENT_REVERB; + break; + + case 0x4d: + effects_set[j].effect_num = ARENA_REVERB; + break; + + case 0x21: + effects_set[j].effect_num = FENDER_63_SPRING_REVERB; + break; + + case 0x0b: + effects_set[j].effect_num = FENDER_65_SPRING_REVERB; + break; + + default: + effects_set[j].effect_num = EMPTY; + break; + } + } + } + + return 0; +} + +int Mustang::save_effects(int slot, char name[24], int number_of_effects, struct fx_pedal_settings effects[2]) +{ + int ret, received; + unsigned char fxknob, repeat; + unsigned char temp[LENGTH], array[LENGTH] = { + 0x1c, 0x01, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + execute[2]=0x00; // why this must be here? + + if(number_of_effects > 2) + repeat = 1; + else + repeat = number_of_effects; + + for(int i = 0; i < repeat; i++) + if(effects[i].effect_num < SINE_CHORUS) + return -1; + + if(effects[0].effect_num>=SINE_CHORUS && effects[0].effect_num<=PITCH_SHIFTER) + { + fxknob = 0x01; + repeat = 1; //just to be sure + } + else + fxknob = 0x02; + array[FXKNOB] = fxknob; + + array[SAVE_SLOT] = slot; + + // set and send the name + if(name[24] != 0x00) + name[24] = 0x00; + for(int i = 0, j = 16; name[i] != 0x00; i++, j++) + array[j] = name[i]; + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); + + array[1] = 0x03; + array[6] = 0x00; + memset(array+16, 0x00, LENGTH-16); + for(int i = 0; i < repeat; i++) + { + array[19] = 0x00; + array[20] = 0x08; + array[21] = 0x01; + array[KNOB6] = 0x00; + + if(effects[i].put_post_amp) + array[FXSLOT] = effects[i].fx_slot+4; + else + array[FXSLOT] = effects[i].fx_slot; + array[KNOB1] = effects[i].knob1; + array[KNOB2] = effects[i].knob2; + array[KNOB3] = effects[i].knob3; + array[KNOB4] = effects[i].knob4; + array[KNOB5] = effects[i].knob5; + // some effects have more knobs + if (effects[i].effect_num == MONO_ECHO_FILTER || + effects[i].effect_num == STEREO_ECHO_FILTER || + effects[i].effect_num == TAPE_DELAY || + effects[i].effect_num == STEREO_TAPE_DELAY) + { + array[KNOB6] = effects[i].knob6; + } + + // fill the form with missing data + switch (effects[i].effect_num) { + case SINE_CHORUS: + array[DSP] = 0x07; + array[EFFECT] = 0x12; + array[19] = 0x01; + array[20] = 0x01; + break; + + case TRIANGLE_CHORUS: + array[DSP] = 0x07; + array[EFFECT] = 0x13; + array[19] = 0x01; + array[20] = 0x01; + break; + + case SINE_FLANGER: + array[DSP] = 0x07; + array[EFFECT] = 0x18; + array[19] = 0x01; + array[20] = 0x01; + break; + + case TRIANGLE_FLANGER: + array[DSP] = 0x07; + array[EFFECT] = 0x19; + array[19] = 0x01; + array[20] = 0x01; + break; + + case VIBRATONE: + array[DSP] = 0x07; + array[EFFECT] = 0x2d; + array[19] = 0x01; + array[20] = 0x01; + break; + + case VINTAGE_TREMOLO: + array[DSP] = 0x07; + array[EFFECT] = 0x40; + array[19] = 0x01; + array[20] = 0x01; + break; + + case SINE_TREMOLO: + array[DSP] = 0x07; + array[EFFECT] = 0x41; + array[19] = 0x01; + array[20] = 0x01; + break; + + case RING_MODULATOR: + array[DSP] = 0x07; + array[EFFECT] = 0x22; + array[19] = 0x01; + if(array[KNOB4] > 0x01) + array[KNOB4] = 0x01; + break; + + case STEP_FILTER: + array[DSP] = 0x07; + array[EFFECT] = 0x29; + array[19] = 0x01; + array[20] = 0x01; + break; + + case PHASER: + array[DSP] = 0x07; + array[EFFECT] = 0x4f; + array[19] = 0x01; + array[20] = 0x01; + if(array[KNOB5] > 0x01) + array[KNOB5] = 0x01; + break; + + case PITCH_SHIFTER: + array[DSP] = 0x07; + array[EFFECT] = 0x1f; + array[19] = 0x01; + break; + + case MONO_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x16; + array[19] = 0x02; + array[20] = 0x01; + break; + + case MONO_ECHO_FILTER: + array[DSP] = 0x08; + array[EFFECT] = 0x43; + array[19] = 0x02; + array[20] = 0x01; + break; + + case STEREO_ECHO_FILTER: + array[DSP] = 0x08; + array[EFFECT] = 0x48; + array[19] = 0x02; + array[20] = 0x01; + break; + + case MULTITAP_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x44; + array[19] = 0x02; + array[20] = 0x01; + break; + + case PING_PONG_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x45; + array[19] = 0x02; + array[20] = 0x01; + break; + + case DUCKING_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x15; + array[19] = 0x02; + array[20] = 0x01; + break; + + case REVERSE_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x46; + array[19] = 0x02; + array[20] = 0x01; + break; + + case TAPE_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x2b; + array[19] = 0x02; + array[20] = 0x01; + break; + + case STEREO_TAPE_DELAY: + array[DSP] = 0x08; + array[EFFECT] = 0x2a; + array[19] = 0x02; + array[20] = 0x01; + break; + + case SMALL_HALL_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x24; + break; + + case LARGE_HALL_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x3a; + break; + + case SMALL_ROOM_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x26; + break; + + case LARGE_ROOM_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x3b; + break; + + case SMALL_PLATE_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4e; + break; + + case LARGE_PLATE_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4b; + break; + + case AMBIENT_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4c; + break; + + case ARENA_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x4d; + break; + + case FENDER_63_SPRING_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x21; + break; + + case FENDER_65_SPRING_REVERB: + array[DSP] = 0x09; + array[EFFECT] = 0x0b; + break; + } + // send packet + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); + } + + execute[FXKNOB] = fxknob; + ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, temp, LENGTH, &received, TMOUT); + execute[FXKNOB] = 0x00; + + return 0; +} + +int Mustang::update(char *filename) +{ + int ret, received; + unsigned char array[LENGTH], number = 0; + FILE *file; +// struct timespec sleep; +// sleep.tv_nsec = NANO_SEC_SLEEP; +// sleep.tv_sec = 0; + + if(amp_hand == NULL) + { + // initialize libusb + ret = libusb_init(NULL); + if (ret) + return ret; + + // get handle for the device + amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, OLD_USB_UPDATE_PID); + if(amp_hand == NULL) + { + amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, NEW_USB_UPDATE_PID); + if(amp_hand == NULL) + { + amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, MINI_USB_UPDATE_PID); + if(amp_hand == NULL) + { + amp_hand = libusb_open_device_with_vid_pid(NULL, USB_UPDATE_VID, FLOOR_USB_UPDATE_PID); + if(amp_hand == NULL) + { + libusb_exit(NULL); + return -100; + } + } + } + } + + // detach kernel driver + ret = libusb_kernel_driver_active(amp_hand, 0); + if(ret) + { + ret = libusb_detach_kernel_driver(amp_hand, 0); + if(ret) + { + stop_amp(); + return ret; + } + } + + // claim the device + ret = libusb_claim_interface(amp_hand, 0); + if(ret) + { + stop_amp(); + return ret; + } + } + else + return -200; + + file = fopen(filename, "rb"); + // send date when firmware was created + fseek(file, 0x1a, SEEK_SET); + memset(array, 0x00, LENGTH); + array[0] = 0x02; + array[1] = 0x03; + array[2] = 0x01; + array[3] = 0x06; + int rc = fread(array+4, 1, 11, file); + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); +// nanosleep(&sleep, NULL); + usleep(10000); + + // send firmware + fseek(file, 0x110, SEEK_SET); + for(;;) + { + memset(array, 0x00, LENGTH); + array[0] = array[1] = 0x03; + array[2] = number; + number++; + array[3] = fread(array+4, 1, LENGTH-8, file); + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); +// nanosleep(&sleep, NULL); + usleep(10000); + if(feof(file)) // if reached end of the file + break; // exit loop + } + fclose(file); + + // send "finished" packet + memset(array, 0x00, LENGTH); + array[0] = 0x04; + array[1] = 0x03; + ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT); + libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT); + + // release claimed interface + ret = libusb_release_interface(amp_hand, 0); + if(ret) + return ret; + + // re-attach kernel driver + ret = libusb_attach_kernel_driver(amp_hand, 0); + if(ret) + return ret; + + // close opened interface + libusb_close(amp_hand); + amp_hand = NULL; + + // stop using libusb + libusb_exit(NULL); + + return 0; +} diff --git a/mustang.h b/mustang.h new file mode 100644 index 0000000..33a68b6 --- /dev/null +++ b/mustang.h @@ -0,0 +1,112 @@ + +#ifndef MUSTANG_H +#define MUSTANG_H + +#include +#include +#include +#include +//#include +#include "effects_enum.h" +#include "data_structs.h" +//#include + +// amp's VID and PID +#define USB_VID 0x1ed8 +#define OLD_USB_PID 0x0004 //Mustang I and II +#define NEW_USB_PID 0x0005 //Mustang III, IV and V +#define V2_USB_PID 0x0014 // Mustang II (and I? !) V2 +#define MINI_USB_PID 0x0010 //Mustang Mini +#define FLOOR_USB_PID 0x0012 //Mustang Floor +#define BRONCO40_USB_PID 0x0a //BRONCO 40 +#define V2_III_PID 0x16 // Mustang III v2 +#define V2_IV_PID 0x17 // Mustang IV v2 (?) + +// amp's VID and PID while in update mode +#define USB_UPDATE_VID 0x1ed8 +#define OLD_USB_UPDATE_PID 0x0006 //Mustang I and II +#define NEW_USB_UPDATE_PID 0x0007 //Mustang III, IV, V +#define MINI_USB_UPDATE_PID 0x0011 //Mustang Mini +#define FLOOR_USB_UPDATE_PID 0x0013 //Mustang Floor +// #define BRONCO40_USB_PID 0x00a //BRONCO 40 + + +// for USB communication +#define TMOUT 500 +#define LENGTH 64 +//#define NANO_SEC_SLEEP 10000000 + +// effect array fields +#define DSP 2 +#define EFFECT 16 +#define FXSLOT 18 +#define KNOB1 32 +#define KNOB2 33 +#define KNOB3 34 +#define KNOB4 35 +#define KNOB5 36 +#define KNOB6 37 + +// amp array fields +#define AMPLIFIER 16 +#define VOLUME 32 +#define GAIN 33 +#define TREBLE 36 +#define MIDDLE 37 +#define BASS 38 +#define CABINET 49 +#define NOISE_GATE 47 +#define THRESHOLD 48 +#define MASTER_VOL 35 +#define GAIN2 34 +#define PRESENCE 39 +#define DEPTH 41 +#define BIAS 42 +#define SAG 51 +#define BRIGHTNESS 52 + +// save fields +#define SAVE_SLOT 4 +#define FXKNOB 3 + +// effect category (slot in 'prev_array'). Used to toggle state. +#define STOMP 0 +#define MOD 1 +#define DELAY 2 +#define REVERB 3 + +class Mustang +{ +public: + Mustang(); + ~Mustang(); + int start_amp(char list[][32]=NULL, char *name=NULL, struct amp_settings *amp_set=NULL, struct fx_pedal_settings *effects_set=NULL); // initialize communication + int stop_amp(void); // terminate communication + int set_effect(struct fx_pedal_settings); + int set_amplifier(struct amp_settings); + int save_on_amp(char *, int); + int load_memory_bank(int, char *name=NULL, struct amp_settings *amp_set=NULL, struct fx_pedal_settings *effects_set=NULL); + int save_effects(int , char *, int , struct fx_pedal_settings *); + int update(char *); + + // State: 1 = off, 0 = on + int effect_toggle(int category, int state); + +private: + libusb_device_handle *amp_hand; // handle for USB communication + unsigned char execute[LENGTH]; // "apply" command sent after each instruction + + // Current state of effects. Read from amp initially and maintained + // as we change it. Major index is DSP# - 6, where: + // + // 0 : Stomp + // 1 : Modulation + // 2 : Delay + // 3 : Reverb + // + unsigned char prev_array[4][LENGTH]; // array used to clear the effect + + int decode_data(unsigned char [6][LENGTH], char *name=NULL, struct amp_settings *amp_set=NULL, struct fx_pedal_settings *effects_set=NULL); +}; + +#endif // MUSTANG_H diff --git a/mustang_midi.cpp b/mustang_midi.cpp new file mode 100644 index 0000000..088ecd5 --- /dev/null +++ b/mustang_midi.cpp @@ -0,0 +1,117 @@ +#include +#include +#include +#include + +#include "mustang.h" + +static Mustang amp; + +static amp_settings amp_parms; +static fx_pedal_settings pedal_parms; +static char name[32]; +static char names[100][32]; + +static int channel; + +void message_action( double deltatime, std::vector< unsigned char > *message, void *userData ) { +#if 1 + unsigned int nBytes = message->size(); + if ( nBytes > 0 ) { + for ( unsigned int i=0; i= 23 && (*message)[1] <= 26 ) { + int category = (*message)[1] - 23; + int value = (*message)[2]; + int state; + if ( value >= 0 && value <= 63 ) state = 1; + else if ( value > 63 && value <= 127 ) state = 0; + rc = amp.effect_toggle( category, state ); + if ( rc ) { + std::cout << "Error: effect_toggle " << category << " failed. rc = " << rc << "\n"; + } + } + } + break; + + default: + break; + } +} + +// void errorcallback( RtError::Type type, const std::string & detail, void *userData ) { +// std::cout << "Error: Code = " << type << ", Msg: " << detail << "\n"; +// } + +void usage() { + std::cerr << "Usage: prog usb_port midi_channel\n"; + exit( 1 ); +} + +int main( int argc, const char **argv ) { + if ( argc != 3 ) usage(); + + char *endptr; + errno = 0; + int port = (int) strtol( argv[1], &endptr, 10 ) - 1; + if ( endptr == argv[0] ) usage(); + if ( port < 0 ) usage(); + + channel = (int) strtol( argv[2], &endptr, 10 ) - 1; + if ( endptr == argv[0] ) usage(); + if ( channel < 0 || channel > 15 ) usage(); + + int rc = amp.start_amp( names, name, &_parms, &pedal_parms ); + if (rc) { + std::cout << "Fender USB initialization failed: " << rc << "\n"; + return 8; + } + + RtMidiIn *input_handler = new RtMidiIn(); + + // See if we have any ports + unsigned int num_ports = input_handler->getPortCount(); + if ( num_ports == 0 ) { + std::cout << "Cannot find a MIDI port\n"; + delete input_handler; + return 8; + } + + // n.b. Midi port rank on the host system is 1..n, but this method + // is normal to 0. + input_handler->openPort( port ); + input_handler->setCallback( &message_action ); + + // Don't want sysex, timing, active sense + input_handler->ignoreTypes( true, true, true ); + + std::cout << "\nTranslating MIDI input - press to quit.\n"; + char input; + std::cin.get(input); + + delete input_handler; + return 0; +}