Implement v2 models. Add test fixture. Make MIDI port normal to zero
This commit is contained in:
parent
ae5b425bf2
commit
df67030396
11 changed files with 623 additions and 55 deletions
44
README.md
44
README.md
|
|
@ -3,6 +3,30 @@
|
||||||
Allow Fender Mustang series guitar amplifiers to be controlled by MIDI
|
Allow Fender Mustang series guitar amplifiers to be controlled by MIDI
|
||||||
messages
|
messages
|
||||||
|
|
||||||
|
# What's New
|
||||||
|
|
||||||
|
The command line parameter for MIDI controller port is now assumed to
|
||||||
|
start at 0 rather than 1 in order to match the way Linux ALSA
|
||||||
|
enumerates devices (see 'Run' below).
|
||||||
|
|
||||||
|
The program has been updated to run as a non-privileged daemon
|
||||||
|
process. You can still invoke it on the command line, but there will
|
||||||
|
be no output to the console and it no longer responds to keypress
|
||||||
|
input. Enter Ctrl-C (SIGINT) to exit.
|
||||||
|
|
||||||
|
I have added the first version of a runtime framework that starts and
|
||||||
|
stops the program automatically based on attached MIDI devices. This
|
||||||
|
seems to be working on a Beaglebone SBC, but has not been extensively
|
||||||
|
tested or documented yet. There is a small amount of customization
|
||||||
|
required to account for your specific amp model and MIDI controller
|
||||||
|
interface. Technically oriented users can probably work this out,
|
||||||
|
otherwise wait a bit until I can refine the packaging and arrange to
|
||||||
|
have the various pieces configured from a common setup file.
|
||||||
|
|
||||||
|
I'm currently working on implementation of amp and effects models
|
||||||
|
added in the Mustang v2 products and hope to have that checked in
|
||||||
|
soon.
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
|
|
||||||
The intent is to implement the published MIDI spec for the Fender
|
The intent is to implement the published MIDI spec for the Fender
|
||||||
|
|
@ -106,12 +130,28 @@ Both the amplifier and MIDI source should be connected first, then:
|
||||||
```
|
```
|
||||||
$ mustang_midi midi_port# midi_listen_channel#
|
$ mustang_midi midi_port# midi_listen_channel#
|
||||||
```
|
```
|
||||||
NOTE: RPi and BBG are a bit fussy about enumeration of new USB
|
NOTE1: I'm not sure about other platforms, but on Linux the MIDI
|
||||||
|
port number is equivalent to the ALSA card index. I had originally
|
||||||
|
treated port as 1..n, but since ALSA (and JACK? Not sure..) starts at
|
||||||
|
0, this has now been changed. You can find the card index for your
|
||||||
|
controller by connecting it to the computer and examining the
|
||||||
|
pseudo-file, e.g.:
|
||||||
|
|
||||||
|
$ cat /proc/asound/cards
|
||||||
|
0 [PCH ]: HDA-Intel - HDA Intel PCH
|
||||||
|
HDA Intel PCH at 0xf7530000 irq 30
|
||||||
|
1 [Interface ]: USB-Audio - USB MS1x1 MIDI Interface
|
||||||
|
M-Audio USB MS1x1 MIDI Interface at usb-0000:00:14.0-1, full speed
|
||||||
|
|
||||||
|
To accept MIDI messages from devices behind the M-Audio interface you
|
||||||
|
would now specify '1' as the MIDI port value.
|
||||||
|
|
||||||
|
NOTE2: RPi and BBG are a bit fussy about enumeration of new USB
|
||||||
devices. If you are not getting proper communication, quit the program
|
devices. If you are not getting proper communication, quit the program
|
||||||
and try replugging both the Fender amp and MIDI controller **after**
|
and try replugging both the Fender amp and MIDI controller **after**
|
||||||
those devices are powered up.
|
those devices are powered up.
|
||||||
|
|
||||||
NOTE2: I've had success using a passive USB hub with the single USB on
|
NOTE3: I've had success using a passive USB hub with the single USB on
|
||||||
the BBG, but YMMV since most USB<->5Pin MIDI converters draw some
|
the BBG, but YMMV since most USB<->5Pin MIDI converters draw some
|
||||||
degree of bus power. A powered hub might be necessary in some
|
degree of bus power. A powered hub might be necessary in some
|
||||||
situations.
|
situations.
|
||||||
|
|
|
||||||
38
amp.h
38
amp.h
|
|
@ -10,6 +10,7 @@ class Mustang;
|
||||||
// F65 Deluxe
|
// F65 Deluxe
|
||||||
// F65 Princeton
|
// F65 Princeton
|
||||||
// F65 Twin
|
// F65 Twin
|
||||||
|
// 60s Thrift
|
||||||
//
|
//
|
||||||
class AmpCC {
|
class AmpCC {
|
||||||
|
|
||||||
|
|
@ -51,13 +52,21 @@ private:
|
||||||
}
|
}
|
||||||
// Cabinet
|
// Cabinet
|
||||||
virtual int cc77( int value ) {
|
virtual int cc77( int value ) {
|
||||||
if ( value < 1 || value > 12 ) return 0;
|
if ( value > 12 ) return 0;
|
||||||
else return discrete_control( 0x11, 0x11, 0x8e, value );
|
else return discrete_control( 0x11, 0x11, 0x8e, value );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dummy in base class
|
// Dummy in base class
|
||||||
virtual int cc78( int value ) { return 0;}
|
virtual int cc78( int value ) { return 0;}
|
||||||
virtual int cc79( int value ) { return 0;}
|
virtual int cc79( int value ) { return 0;}
|
||||||
|
|
||||||
|
// Noise Gate Custom Threshold
|
||||||
|
virtual int cc90( int value ) {
|
||||||
|
if ( value > 9 ) return 0;
|
||||||
|
else return discrete_control( 0x10, 0x10, 0x86, value );
|
||||||
|
}
|
||||||
|
// Noise Gate Custom Depth
|
||||||
|
virtual int cc91( int value ) { return continuous_control( 0x09, 0x09, 0x0c, value );}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -104,6 +113,7 @@ private:
|
||||||
// British 80s
|
// British 80s
|
||||||
// American 90s
|
// American 90s
|
||||||
// Metal 2000
|
// Metal 2000
|
||||||
|
// British Watt
|
||||||
//
|
//
|
||||||
class AmpCC4 : public AmpCC {
|
class AmpCC4 : public AmpCC {
|
||||||
public:
|
public:
|
||||||
|
|
@ -122,11 +132,37 @@ class AmpCC5 : public AmpCC {
|
||||||
public:
|
public:
|
||||||
AmpCC5( Mustang * theAmp ) : AmpCC(theAmp) {}
|
AmpCC5( Mustang * theAmp ) : AmpCC(theAmp) {}
|
||||||
private:
|
private:
|
||||||
|
// No sag / bias
|
||||||
|
virtual int cc74( int value ) { return 0;}
|
||||||
|
virtual int cc75( int value ) { return 0;}
|
||||||
|
// No pres / master
|
||||||
virtual int cc78( int value ) { return 0;}
|
virtual int cc78( int value ) { return 0;}
|
||||||
virtual int cc79( int value ) { return 0;}
|
virtual int cc79( int value ) { return 0;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// British Color
|
||||||
|
//
|
||||||
|
class AmpCC6 : public AmpCC {
|
||||||
|
public:
|
||||||
|
AmpCC6( Mustang * theAmp ) : AmpCC(theAmp) {}
|
||||||
|
private:
|
||||||
|
// Master Volume
|
||||||
|
virtual int cc79( int value ) { return continuous_control( 0x03, 0x03, 0x0c, value );}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// F57 Twin
|
||||||
|
//
|
||||||
|
class AmpCC7 : public AmpCC {
|
||||||
|
public:
|
||||||
|
AmpCC7( Mustang * theAmp ) : AmpCC(theAmp) {}
|
||||||
|
private:
|
||||||
|
// Presence
|
||||||
|
virtual int cc78( int value ) { return continuous_control( 0x07, 0x07, 0x0c, value );}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Null Amp
|
// Null Amp
|
||||||
//
|
//
|
||||||
class NullAmpCC : public AmpCC {
|
class NullAmpCC : public AmpCC {
|
||||||
|
|
|
||||||
|
|
@ -93,3 +93,40 @@ static unsigned char metal_2k[] = {
|
||||||
0x00, 0x08, 0x08, 0x01, 0x00, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x08, 0x08, 0x01, 0x00, 0x01, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// V2 Only:
|
||||||
|
|
||||||
|
static unsigned char studio_preamp[] = {
|
||||||
|
0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xff, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x0d, 0x0d, 0x0d, 0x00,
|
||||||
|
0x00, 0x00, 0x0d, 0x01, 0x00, 0x01, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char sixties_thrift[] = {
|
||||||
|
0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xac, 0x81, 0x81, 0x81, 0xac, 0x81, 0x9d, 0x81, 0x81, 0x81, 0x81, 0x81, 0x0f, 0x0f, 0x0f, 0x00,
|
||||||
|
0x00, 0x01, 0x0f, 0x01, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char brit_watts[] = {
|
||||||
|
0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xba, 0x9d, 0x81, 0xff, 0xba, 0x98, 0xa6, 0x87, 0x81, 0x81, 0x81, 0x81, 0x11, 0x11, 0x11, 0x00,
|
||||||
|
0x00, 0x0a, 0x11, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char brit_color[] = {
|
||||||
|
0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xac, 0x8c, 0x81, 0x81, 0x9d, 0x64, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x10, 0x10, 0x10, 0x01,
|
||||||
|
0x00, 0x08, 0x10, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char f57_twin[] = {
|
||||||
|
0x1c, 0x03, 0x05, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xac, 0x4e, 0x81, 0x81, 0xac, 0x7b, 0x9d, 0xbd, 0x81, 0x81, 0x81, 0x81, 0x0e, 0x0e, 0x0e, 0x00,
|
||||||
|
0x00, 0x09, 0x0e, 0x01, 0x00, 0x01, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
||||||
2
delay.h
2
delay.h
|
|
@ -65,6 +65,8 @@ class MultitapDelayCC : public DelayCC {
|
||||||
public:
|
public:
|
||||||
MultitapDelayCC( Mustang * theAmp ) : DelayCC(theAmp) {}
|
MultitapDelayCC( Mustang * theAmp ) : DelayCC(theAmp) {}
|
||||||
private:
|
private:
|
||||||
|
// Delay Time
|
||||||
|
virtual int cc50( int value ) { return continuous_control( 0x01, 0x01, 0x08, value );}
|
||||||
// Feedback
|
// Feedback
|
||||||
virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );}
|
virtual int cc51( int value ) { return continuous_control( 0x02, 0x02, 0x01, value );}
|
||||||
// Brightness
|
// Brightness
|
||||||
|
|
|
||||||
|
|
@ -82,3 +82,26 @@ static unsigned char pitch_shifter[] = {
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// V2 Only:
|
||||||
|
|
||||||
|
static unsigned char mod_wah[] = {
|
||||||
|
0x1c, 0x03, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xf4, 0x00, 0x04, 0x01, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xff, 0x81, 0x01, 0xff, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char mod_touch_wah[] = {
|
||||||
|
0x1c, 0x03, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xf5, 0x00, 0x04, 0x01, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xed, 0x81, 0x07, 0xff, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char diatonic_pitch_shift[] = {
|
||||||
|
0x1c, 0x03, 0x07, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x1f, 0x10, 0x04, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x56, 0x09, 0x04, 0x05, 0xc8, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
||||||
156
mustang.cpp
156
mustang.cpp
|
|
@ -16,11 +16,25 @@
|
||||||
#include "mod_defaults.h"
|
#include "mod_defaults.h"
|
||||||
#include "stomp_defaults.h"
|
#include "stomp_defaults.h"
|
||||||
|
|
||||||
|
Mustang::usb_id Mustang::ids[] = {
|
||||||
|
{ OLD_USB_PID, 0x03, false },
|
||||||
|
{ NEW_USB_PID, 0xc1, false },
|
||||||
|
{ V2_USB_PID, 0x03, false },
|
||||||
|
{ MINI_USB_PID, 0x03, false },
|
||||||
|
{ FLOOR_USB_PID, 0x03, false },
|
||||||
|
{ BRONCO40_USB_PID, 0x03, false },
|
||||||
|
{ V2_III_PID, 0xc1, true },
|
||||||
|
{ V2_IV_PID, 0xc1, true },
|
||||||
|
{ 0, 0x00, false }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Mustang::Mustang()
|
Mustang::Mustang()
|
||||||
{
|
{
|
||||||
amp_hand = NULL;
|
amp_hand = NULL;
|
||||||
curr_amp = NULL;
|
curr_amp = NULL;
|
||||||
tuner_active = false;
|
tuner_active = false;
|
||||||
|
isV2 = false;
|
||||||
|
|
||||||
// "apply efect" command
|
// "apply efect" command
|
||||||
memset(execute, 0x00, LENGTH);
|
memset(execute, 0x00, LENGTH);
|
||||||
|
|
@ -46,6 +60,7 @@ Mustang::~Mustang()
|
||||||
int Mustang::start_amp(void)
|
int Mustang::start_amp(void)
|
||||||
{
|
{
|
||||||
int ret, received;
|
int ret, received;
|
||||||
|
static int init_value = -1;
|
||||||
unsigned char array[LENGTH];
|
unsigned char array[LENGTH];
|
||||||
|
|
||||||
if(amp_hand == NULL)
|
if(amp_hand == NULL)
|
||||||
|
|
@ -55,17 +70,18 @@ int Mustang::start_amp(void)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
// get handle for the device
|
for ( int idx=0; ids[idx].pid != 0; idx++ ) {
|
||||||
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, ids[idx].pid)) != NULL ) {
|
||||||
if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, NEW_USB_PID)) == NULL)
|
init_value = ids[idx].init_value;
|
||||||
if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, V2_USB_PID)) == NULL)
|
isV2 = ids[idx].isV2;
|
||||||
if((amp_hand = libusb_open_device_with_vid_pid(NULL, USB_VID, MINI_USB_PID)) == NULL)
|
break;
|
||||||
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)
|
if ( init_value < 0 ) {
|
||||||
{
|
// No amp found
|
||||||
libusb_exit(NULL);
|
libusb_exit( NULL );
|
||||||
|
fprintf( stderr, "S - No Mustang USB device found\n" );
|
||||||
return -100;
|
return -100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,13 +115,7 @@ int Mustang::start_amp(void)
|
||||||
|
|
||||||
memset(array, 0x00, LENGTH);
|
memset(array, 0x00, LENGTH);
|
||||||
array[0] = 0x1a;
|
array[0] = 0x1a;
|
||||||
|
array[1] = init_value;
|
||||||
// This seems model specific
|
|
||||||
// Perhaps for Mustang II?
|
|
||||||
// array[1] = 0x03;
|
|
||||||
|
|
||||||
// Correct value for Mustang III
|
|
||||||
array[1] = 0xc1;
|
|
||||||
|
|
||||||
libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT);
|
libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT);
|
||||||
libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT);
|
libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT);
|
||||||
|
|
@ -230,8 +240,11 @@ int Mustang::tunerMode( int value )
|
||||||
void Mustang::updateAmpObj(void) {
|
void Mustang::updateAmpObj(void) {
|
||||||
|
|
||||||
int curr = curr_state[AMP_STATE][MODEL];
|
int curr = curr_state[AMP_STATE][MODEL];
|
||||||
|
AmpCC * new_amp = NULL;
|
||||||
|
|
||||||
switch (curr) {
|
switch (curr) {
|
||||||
case 0:
|
case 0:
|
||||||
|
// No amp
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F57_DELUXE_ID:
|
case F57_DELUXE_ID:
|
||||||
|
|
@ -239,42 +252,51 @@ void Mustang::updateAmpObj(void) {
|
||||||
case F65_DELUXE_ID:
|
case F65_DELUXE_ID:
|
||||||
case F65_PRINCETON_ID:
|
case F65_PRINCETON_ID:
|
||||||
case F65_TWIN_ID:
|
case F65_TWIN_ID:
|
||||||
delete curr_amp;
|
case S60S_THRIFT_ID:
|
||||||
curr_amp = new AmpCC(this);
|
new_amp = new AmpCC(this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F59_BASSMAN_ID:
|
case F59_BASSMAN_ID:
|
||||||
case BRIT_70S_ID:
|
case BRIT_70S_ID:
|
||||||
delete curr_amp;
|
new_amp = new AmpCC1(this);
|
||||||
curr_amp = new AmpCC1(this);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F_SUPERSONIC_ID:
|
case F_SUPERSONIC_ID:
|
||||||
delete curr_amp;
|
new_amp = new AmpCC2(this);
|
||||||
curr_amp = new AmpCC2(this);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BRIT_60S_ID:
|
case BRIT_60S_ID:
|
||||||
delete curr_amp;
|
new_amp = new AmpCC3(this);
|
||||||
curr_amp = new AmpCC3(this);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BRIT_80S_ID:
|
case BRIT_80S_ID:
|
||||||
case US_90S_ID:
|
case US_90S_ID:
|
||||||
case METAL_2K_ID:
|
case METAL_2K_ID:
|
||||||
delete curr_amp;
|
case BRIT_WATT_ID:
|
||||||
curr_amp = new AmpCC4(this);
|
new_amp = new AmpCC4(this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STUDIO_PREAMP_ID:
|
case STUDIO_PREAMP_ID:
|
||||||
delete curr_amp;
|
new_amp = new AmpCC5(this);
|
||||||
curr_amp = new AmpCC5(this);
|
break;
|
||||||
|
|
||||||
|
case BRIT_COLOR_ID:
|
||||||
|
new_amp = new AmpCC6(this);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case F57_TWIN_ID:
|
||||||
|
new_amp = new AmpCC7(this);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf( stderr, "W - Amp id %x not supported yet\n", curr );
|
fprintf( stderr, "W - Amp id %x not supported yet\n", curr );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( (new_amp!=NULL) && (new_amp!=curr_amp) ) {
|
||||||
|
delete curr_amp;
|
||||||
|
curr_amp = new_amp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -538,9 +560,33 @@ int Mustang::setAmp( int ord ) {
|
||||||
array = metal_2k;
|
array = metal_2k;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf( stderr, "W - Amp select %d not yet supported\n", ord );
|
if ( isV2 ) {
|
||||||
|
switch (ord) {
|
||||||
|
case 13:
|
||||||
|
array = studio_preamp;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
array = f57_twin;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
array = sixties_thrift;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
array = brit_watts;
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
array = brit_color;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf( stderr, "W - Amp select %d not supported\n", ord );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf( stderr, "W - Amp select %d not supported\n", ord );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Setup amp personality
|
// Setup amp personality
|
||||||
ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT);
|
ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT);
|
||||||
|
|
@ -739,10 +785,28 @@ int Mustang::setMod( int ord ) {
|
||||||
case 11:
|
case 11:
|
||||||
array = pitch_shifter;
|
array = pitch_shifter;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
if ( isV2 ) {
|
||||||
|
switch (ord) {
|
||||||
|
case 12:
|
||||||
|
array = mod_wah;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
array = mod_touch_wah;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
array = diatonic_pitch_shift;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf( stderr, "W - Mod select %d not supported\n", ord );
|
fprintf( stderr, "W - Mod select %d not supported\n", ord );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf( stderr, "W - Mod select %d not supported\n", ord );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
array[FXSLOT] = curr_state[MOD_STATE][FXSLOT];
|
array[FXSLOT] = curr_state[MOD_STATE][FXSLOT];
|
||||||
|
|
||||||
|
|
@ -785,7 +849,13 @@ int Mustang::setStomp( int ord ) {
|
||||||
array = fuzz;
|
array = fuzz;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
|
if ( isV2 ) {
|
||||||
|
fprintf( stderr, "W - Stomp select %d not supported\n", ord );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
array = fuzz_touch_wah;
|
array = fuzz_touch_wah;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
array = simple_comp;
|
array = simple_comp;
|
||||||
|
|
@ -793,10 +863,34 @@ int Mustang::setStomp( int ord ) {
|
||||||
case 7:
|
case 7:
|
||||||
array = compressor;
|
array = compressor;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
if ( isV2 ) {
|
||||||
|
switch (ord) {
|
||||||
|
case 8:
|
||||||
|
array = ranger_boost;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
array = green_box;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
array = orange_box;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
array = black_box;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
array = big_fuzz;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf( stderr, "W - Stomp select %d not supported\n", ord );
|
fprintf( stderr, "W - Stomp select %d not supported\n", ord );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf( stderr, "W - Stomp select %d not supported\n", ord );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
array[FXSLOT] = curr_state[STOMP_STATE][FXSLOT];
|
array[FXSLOT] = curr_state[STOMP_STATE][FXSLOT];
|
||||||
|
|
||||||
|
|
|
||||||
35
mustang.h
35
mustang.h
|
|
@ -33,7 +33,7 @@
|
||||||
// for USB communication
|
// for USB communication
|
||||||
#define TMOUT 500
|
#define TMOUT 500
|
||||||
#define LENGTH 64
|
#define LENGTH 64
|
||||||
//#define NANO_SEC_SLEEP 10000000
|
|
||||||
|
|
||||||
// effect array fields
|
// effect array fields
|
||||||
#define DSP 2
|
#define DSP 2
|
||||||
|
|
@ -110,8 +110,9 @@
|
||||||
#define BRIT_80S_ID 0x5e
|
#define BRIT_80S_ID 0x5e
|
||||||
#define US_90S_ID 0x5d
|
#define US_90S_ID 0x5d
|
||||||
#define METAL_2K_ID 0x6d
|
#define METAL_2K_ID 0x6d
|
||||||
#define STUDIO_PREAMP_ID 0xf1
|
|
||||||
|
|
||||||
|
// v2 amp only
|
||||||
|
#define STUDIO_PREAMP_ID 0xf1
|
||||||
#define F57_TWIN_ID 0xf6
|
#define F57_TWIN_ID 0xf6
|
||||||
#define S60S_THRIFT_ID 0xf9
|
#define S60S_THRIFT_ID 0xf9
|
||||||
#define BRIT_WATT_ID 0xff
|
#define BRIT_WATT_ID 0xff
|
||||||
|
|
@ -153,15 +154,30 @@
|
||||||
#define PHASER_ID 0x4f
|
#define PHASER_ID 0x4f
|
||||||
#define PITCH_SHIFT_ID 0x1f
|
#define PITCH_SHIFT_ID 0x1f
|
||||||
|
|
||||||
|
// v2 mod only
|
||||||
|
#define M_WAH_ID 0xf4
|
||||||
|
#define M_TOUCH_WAH_ID 0xf5
|
||||||
|
#define DIA_PSHIFT_ID 0x1f
|
||||||
|
|
||||||
// Stomp model id values
|
// Stomp model id values
|
||||||
#define OVERDRIVE_ID 0x3c
|
#define OVERDRIVE_ID 0x3c
|
||||||
#define WAH_ID 0x49
|
#define WAH_ID 0x49
|
||||||
#define TOUCH_WAH_ID 0x4a
|
#define TOUCH_WAH_ID 0x4a
|
||||||
#define FUZZ_ID 0x1a
|
#define FUZZ_ID 0x1a
|
||||||
|
|
||||||
|
// This is not present in v2:
|
||||||
#define FUZZ_TWAH_ID 0x1c
|
#define FUZZ_TWAH_ID 0x1c
|
||||||
|
|
||||||
#define SIMPLE_COMP_ID 0x88
|
#define SIMPLE_COMP_ID 0x88
|
||||||
#define COMP_ID 0x07
|
#define COMP_ID 0x07
|
||||||
|
|
||||||
|
// v2 stomp only
|
||||||
|
#define RANGE_BOOST_ID 0x03
|
||||||
|
#define GREEN_BOX_ID 0xba
|
||||||
|
#define ORANGE_BOX_ID 0x10
|
||||||
|
#define BLACK_BOX_ID 0x11
|
||||||
|
#define BIG_FUZZ_ID 0x0f
|
||||||
|
|
||||||
|
|
||||||
class AmpCC;
|
class AmpCC;
|
||||||
class ReverbCC;
|
class ReverbCC;
|
||||||
|
|
@ -213,9 +229,24 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
struct usb_id {
|
||||||
|
// product id
|
||||||
|
int pid;
|
||||||
|
// magic value for init packet
|
||||||
|
int init_value;
|
||||||
|
// v2?
|
||||||
|
bool isV2;
|
||||||
|
};
|
||||||
|
|
||||||
|
// For device probe
|
||||||
|
static usb_id ids[];
|
||||||
|
|
||||||
libusb_device_handle *amp_hand; // handle for USB communication
|
libusb_device_handle *amp_hand; // handle for USB communication
|
||||||
unsigned char execute[LENGTH]; // "apply" command sent after each instruction
|
unsigned char execute[LENGTH]; // "apply" command sent after each instruction
|
||||||
|
|
||||||
|
bool isV2;
|
||||||
|
|
||||||
// Current state of effects. Read from amp initially and maintained
|
// Current state of effects. Read from amp initially and maintained
|
||||||
// as we change it. Major index is DSP# - 6, where:
|
// as we change it. Major index is DSP# - 6, where:
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ mustang_vid = 0x1ed8
|
||||||
mustang_pid = 0x0016
|
mustang_pid = 0x0016
|
||||||
|
|
||||||
# Controller MIDI device
|
# Controller MIDI device
|
||||||
midi_device = 2
|
midi_device = 1
|
||||||
|
|
||||||
# MIDI listen channel
|
# MIDI listen channel
|
||||||
midi_channel = 1
|
midi_channel = 1
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo
|
||||||
#if 0
|
#if 0
|
||||||
unsigned int nBytes = message->size();
|
unsigned int nBytes = message->size();
|
||||||
if ( nBytes > 0 ) {
|
if ( nBytes > 0 ) {
|
||||||
for ( unsigned int i=0; i<nBytes; i++ )
|
fprintf( stdout, "%02x %d %d\n", (int)message->at(0), (int)message->at(1), (int)message->at(2) );
|
||||||
std::cout << "Byte " << i << " = " << (int)message->at(i) << ", ";
|
|
||||||
std::cout << "stamp = " << deltatime << std::endl << std::flush;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -124,6 +122,7 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// void errorcallback( RtError::Type type, const std::string & detail, void *userData ) {
|
// void errorcallback( RtError::Type type, const std::string & detail, void *userData ) {
|
||||||
|
|
@ -131,7 +130,9 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo
|
||||||
// }
|
// }
|
||||||
|
|
||||||
void usage() {
|
void usage() {
|
||||||
std::cerr << "Usage: prog usb_port midi_channel\n";
|
fprintf( stderr, "Usage: mustang_midi <controller_port#> <midi_channel#>\n" );
|
||||||
|
fprintf( stderr, " port = 0..n, channel = 1..16\n" );
|
||||||
|
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,7 +141,7 @@ int main( int argc, const char **argv ) {
|
||||||
|
|
||||||
char *endptr;
|
char *endptr;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
int port = (int) strtol( argv[1], &endptr, 10 ) - 1;
|
int port = (int) strtol( argv[1], &endptr, 10 );
|
||||||
if ( endptr == argv[0] ) usage();
|
if ( endptr == argv[0] ) usage();
|
||||||
if ( port < 0 ) usage();
|
if ( port < 0 ) usage();
|
||||||
|
|
||||||
|
|
@ -163,10 +164,8 @@ int main( int argc, const char **argv ) {
|
||||||
delete input_handler;
|
delete input_handler;
|
||||||
return 8;
|
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->openPort( port );
|
||||||
|
// input_handler->openVirtualPort( "TestPort" );
|
||||||
input_handler->setCallback( &message_action );
|
input_handler->setCallback( &message_action );
|
||||||
|
|
||||||
// Don't want sysex, timing, active sense
|
// Don't want sysex, timing, active sense
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ static unsigned char fuzz[] = {
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fuzz Touch Wah in original only!
|
||||||
|
|
||||||
static unsigned char fuzz_touch_wah[] = {
|
static unsigned char fuzz_touch_wah[] = {
|
||||||
0x1c, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x1c, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x1c, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x1c, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
|
@ -54,3 +56,40 @@ static unsigned char compressor[] = {
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// V2 Only:
|
||||||
|
|
||||||
|
static unsigned char ranger_boost[] = {
|
||||||
|
0x1c, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x03, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x64, 0xba, 0x01, 0x9b, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char green_box[] = {
|
||||||
|
0x1c, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xba, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x81, 0xb1, 0x8c, 0xff, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char orange_box[] = {
|
||||||
|
0x1c, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x10, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x81, 0x81, 0x81, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char black_box[] = {
|
||||||
|
0x1c, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x11, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x81, 0x81, 0x56, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char big_fuzz[] = {
|
||||||
|
0x1c, 0x03, 0x06, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x0f, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xac, 0xac, 0x73, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
||||||
267
test.py
Executable file
267
test.py
Executable file
|
|
@ -0,0 +1,267 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
# Use aconnectgui to wire Midi Through Port-0 out to
|
||||||
|
# mustang bridge virtual input port name
|
||||||
|
|
||||||
|
# OR
|
||||||
|
|
||||||
|
# hirsch@z87:~$ aconnect -o
|
||||||
|
# client 14: 'Midi Through' [type=kernel]
|
||||||
|
# 0 'Midi Through Port-0'
|
||||||
|
# client 128: 'RtMidi Input Client' [type=user]
|
||||||
|
# 0 'TestPort '
|
||||||
|
#
|
||||||
|
# Given the above, open RtMidi as: 'RtMidi Input Client 128:0'
|
||||||
|
#
|
||||||
|
# outport = mido.open_output('Midi Through 14:0')
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
import sys
|
||||||
|
import itertools as it
|
||||||
|
import mido
|
||||||
|
mido.set_backend('mido.backends.rtmidi')
|
||||||
|
|
||||||
|
pc = mido.Message('program_change')
|
||||||
|
cc = mido.Message('control_change')
|
||||||
|
|
||||||
|
def analog_send( outport, sleeptime=0.25 ):
|
||||||
|
for value in [ 0, 32, 64, 96, 127, 96, 64, 32, 0 ]:
|
||||||
|
cc.value = value
|
||||||
|
outport.send( cc )
|
||||||
|
sleep( sleeptime )
|
||||||
|
|
||||||
|
def discrete_send( outport, max ):
|
||||||
|
for value in it.chain( range(0,max+1), range(max,-1,-1) ):
|
||||||
|
cc.value = value
|
||||||
|
outport.send( cc )
|
||||||
|
sleep( 0.25 )
|
||||||
|
|
||||||
|
# Screen 1 is the same for all models
|
||||||
|
def amp_screen1( outport ):
|
||||||
|
for i in range( 69, 74 ):
|
||||||
|
cc.control = i
|
||||||
|
analog_send( outport )
|
||||||
|
|
||||||
|
# Some variation in screen 2 across models
|
||||||
|
def amp_screen2( outport, bias_sag, extra ):
|
||||||
|
if bias_sag:
|
||||||
|
cc.control = 74
|
||||||
|
discrete_send( outport, 2 )
|
||||||
|
cc.control = 75
|
||||||
|
analog_send( outport )
|
||||||
|
|
||||||
|
cc.control = 76
|
||||||
|
discrete_send( outport, 4 )
|
||||||
|
|
||||||
|
cc.control = 77
|
||||||
|
discrete_send( outport, 12 )
|
||||||
|
|
||||||
|
if extra:
|
||||||
|
cc.control = 78
|
||||||
|
analog_send( outport )
|
||||||
|
cc.control = 79
|
||||||
|
analog_send( outport )
|
||||||
|
|
||||||
|
# Step through all amp models
|
||||||
|
def amp_select( outport ):
|
||||||
|
cc.control = 68
|
||||||
|
for i in range( 0, 13 ):
|
||||||
|
cc.value = i
|
||||||
|
outport.send( cc )
|
||||||
|
sleep( 0.5 )
|
||||||
|
|
||||||
|
def run_amp_test( struct, outport ):
|
||||||
|
raw_input( "Hit ENTER to run amp model select test...\n" )
|
||||||
|
amp_select( outport )
|
||||||
|
|
||||||
|
for i in range( 0, len(struct) ):
|
||||||
|
amp_rec = struct[i]
|
||||||
|
|
||||||
|
raw_input( "Hit ENTER to run parm edit check for %s\n" % amp_rec[0] )
|
||||||
|
cc.control = 68
|
||||||
|
cc.value = amp_rec[1]
|
||||||
|
outport.send( cc )
|
||||||
|
|
||||||
|
raw_input( "Enter amp edit mode on Mustang and hit ENTER to proceed...\n" )
|
||||||
|
amp_screen1( outport )
|
||||||
|
|
||||||
|
raw_input( "Step to amp edit screen 2 and hit ENTER...\n" )
|
||||||
|
amp_screen2( outport, amp_rec[2], amp_rec[3] )
|
||||||
|
|
||||||
|
# Step through all reverb models
|
||||||
|
def reverb_select( outport ):
|
||||||
|
cc.control = 58
|
||||||
|
for i in range( 0, 11 ):
|
||||||
|
cc.value = i
|
||||||
|
outport.send( cc )
|
||||||
|
sleep( 0.5 )
|
||||||
|
|
||||||
|
def run_reverb_test( outport ):
|
||||||
|
raw_input( "Hit ENTER to run reverb model select test...\n" )
|
||||||
|
reverb_select( outport )
|
||||||
|
|
||||||
|
raw_input( "Enter Reverb edit mode and hit ENTER...\n" )
|
||||||
|
for i in range ( 59, 64 ):
|
||||||
|
cc.control = i
|
||||||
|
analog_send( outport )
|
||||||
|
sleep( 0.25 )
|
||||||
|
|
||||||
|
# Step through all delay models
|
||||||
|
def delay_select( outport ):
|
||||||
|
cc.control = 48
|
||||||
|
for i in range( 0, 10 ):
|
||||||
|
cc.value = i
|
||||||
|
outport.send( cc )
|
||||||
|
sleep( 0.5 )
|
||||||
|
|
||||||
|
def run_delay_test( struct, outport ):
|
||||||
|
raw_input( "Hit ENTER to run delay model select test...\n" )
|
||||||
|
delay_select( outport )
|
||||||
|
|
||||||
|
for i in range( 0, len(struct) ):
|
||||||
|
delay_rec = struct[i]
|
||||||
|
|
||||||
|
raw_input( "Hit ENTER to run parm edit check for %s\n" % delay_rec[0] )
|
||||||
|
cc.control = 48
|
||||||
|
cc.value = delay_rec[1]
|
||||||
|
outport.send( cc )
|
||||||
|
|
||||||
|
raw_input( "Enter delay edit mode on Mustang and hit ENTER to proceed...\n" )
|
||||||
|
for i in range( 49, 54 ):
|
||||||
|
cc.control = i
|
||||||
|
# Multitap Delay has a single discrete control
|
||||||
|
if i==53 and delay_rec[2]:
|
||||||
|
discrete_send( outport, 3 )
|
||||||
|
else:
|
||||||
|
analog_send( outport )
|
||||||
|
|
||||||
|
if delay_rec[3]:
|
||||||
|
analog_send( outport )
|
||||||
|
|
||||||
|
# Step through all mod models
|
||||||
|
def mod_select( outport ):
|
||||||
|
cc.control = 38
|
||||||
|
for i in range( 0, 12 ):
|
||||||
|
cc.value = i
|
||||||
|
outport.send( cc )
|
||||||
|
sleep( 0.5 )
|
||||||
|
|
||||||
|
def run_mod_test( struct, outport ):
|
||||||
|
raw_input( "Hit ENTER to run mod model select test...\n" )
|
||||||
|
mod_select( outport )
|
||||||
|
|
||||||
|
for i in range( 0, len(struct) ):
|
||||||
|
mod_rec = struct[i]
|
||||||
|
|
||||||
|
raw_input( "Hit ENTER to run parm edit check for %s\n" % mod_rec[0] )
|
||||||
|
cc.control = 38
|
||||||
|
cc.value = mod_rec[1]
|
||||||
|
outport.send( cc )
|
||||||
|
|
||||||
|
raw_input( "Enter mod edit mode on Mustang and hit ENTER to proceed...\n" )
|
||||||
|
for i in range( 39, 44 ):
|
||||||
|
cc.control = i
|
||||||
|
if (i==42 and mod_rec[2]) or (i==43 and mod_rec[3]):
|
||||||
|
discrete_send( outport, 1 )
|
||||||
|
else:
|
||||||
|
analog_send( outport )
|
||||||
|
|
||||||
|
# Step through all stomp models
|
||||||
|
def stomp_select( outport ):
|
||||||
|
cc.control = 28
|
||||||
|
for i in range( 0, 8 ):
|
||||||
|
cc.value = i
|
||||||
|
outport.send( cc )
|
||||||
|
sleep( 0.5 )
|
||||||
|
|
||||||
|
def run_stomp_test( struct, outport ):
|
||||||
|
raw_input( "Hit ENTER to run stomp model select test...\n" )
|
||||||
|
stomp_select( outport )
|
||||||
|
|
||||||
|
for i in range( 0, len(struct) ):
|
||||||
|
stomp_rec = struct[i]
|
||||||
|
|
||||||
|
raw_input( "Hit ENTER to run parm edit check for %s\n" % stomp_rec[0] )
|
||||||
|
cc.control = 28
|
||||||
|
cc.value = stomp_rec[1]
|
||||||
|
outport.send( cc )
|
||||||
|
|
||||||
|
raw_input( "Enter stomp edit mode on Mustang and hit ENTER to proceed...\n" )
|
||||||
|
for i in range( 29, 34 ):
|
||||||
|
cc.control = i
|
||||||
|
if i==33 and stomp_rec[2]:
|
||||||
|
discrete_send( outport, 1 )
|
||||||
|
elif i==29 and stomp_rec[3]:
|
||||||
|
discrete_send( outport, 3 )
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
analog_send( outport )
|
||||||
|
|
||||||
|
# Step through program changes
|
||||||
|
def program_change_test( outport ):
|
||||||
|
raw_input( "Hit ENTER to run program change test...\n" )
|
||||||
|
for i in ( 0, 25, 75, 99, 60, 40, 20, 0 ):
|
||||||
|
pc.program = i
|
||||||
|
outport.send( pc )
|
||||||
|
sleep( 0.5 )
|
||||||
|
|
||||||
|
args = sys.argv
|
||||||
|
|
||||||
|
if not len(args) == 3:
|
||||||
|
print "Usage: test.py <virtual_port_name> <midi_channel>\n"
|
||||||
|
sys.exit( 1 )
|
||||||
|
|
||||||
|
try:
|
||||||
|
pc.channel = cc.channel = int( args[2] ) - 1
|
||||||
|
except ValueError:
|
||||||
|
print "Arg2 must be numeric!\n"
|
||||||
|
sys.exit( 1 )
|
||||||
|
|
||||||
|
outport = mido.open_output( args[1] )
|
||||||
|
|
||||||
|
program_change_test( outport )
|
||||||
|
|
||||||
|
# Model # 33 Dig?
|
||||||
|
stomp_test = (
|
||||||
|
( "Overdrive", 1, False, False ),
|
||||||
|
( "Wah", 2, True, False ),
|
||||||
|
( "Simple Comp", 6, False, True ),
|
||||||
|
( "Comp", 7, False, False )
|
||||||
|
)
|
||||||
|
|
||||||
|
run_stomp_test( stomp_test, outport )
|
||||||
|
|
||||||
|
# Model # 42 Dig? 43 Dig?
|
||||||
|
mod_test = (
|
||||||
|
( "Sine Chorus", 1, False, False ),
|
||||||
|
( "Vibratone", 5, False, False ),
|
||||||
|
( "Vintage Trem", 6, False, False ),
|
||||||
|
( "Ring Mod", 8, True, False ),
|
||||||
|
( "Phaser", 10, False, True ),
|
||||||
|
( "Pitch Shift", 11, False, False )
|
||||||
|
)
|
||||||
|
|
||||||
|
run_mod_test( mod_test, outport )
|
||||||
|
|
||||||
|
run_reverb_test( outport )
|
||||||
|
|
||||||
|
# Model # 53 Dig?, Has 54?
|
||||||
|
delay_test = (
|
||||||
|
( "Mono Delay", 1, False, False ),
|
||||||
|
( "Multitap", 4, True, False ),
|
||||||
|
( "Tape Delay", 8, False, False )
|
||||||
|
)
|
||||||
|
|
||||||
|
run_delay_test( delay_test, outport )
|
||||||
|
|
||||||
|
# Model, #, Bias/Sag?, Extra?
|
||||||
|
amp_test = (
|
||||||
|
( "Fender 65 Twin", 6, True, False ),
|
||||||
|
( "Fender SuperSonic", 7, True, True ),
|
||||||
|
( "British 60s", 8, True, True ),
|
||||||
|
( "British 70s", 9, True, True ),
|
||||||
|
( "British 80s", 10, True, True )
|
||||||
|
)
|
||||||
|
|
||||||
|
run_amp_test( amp_test, outport )
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue