Implement reverb CCs

This commit is contained in:
hirsch 2016-06-24 13:06:05 -04:00
parent 7e45418d0f
commit fae1d3c727
7 changed files with 299 additions and 6 deletions

11
50-mustang.rules Normal file
View file

@ -0,0 +1,11 @@
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0004", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0005", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0006", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0007", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0010", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0011", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0012", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0013", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0014", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0015", GROUP="plugdev"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="1ed8", ATTRS{idProduct}=="0016", GROUP="plugdev"

View file

@ -4,6 +4,7 @@
#include "magic.h"
#include "amp_defaults.h"
#include "reverb_defaults.h"
Mustang::Mustang()
{
@ -130,6 +131,7 @@ int Mustang::start_amp(void)
for(j = 0; j < 7; i++, j++) memcpy(curr_state[j], received_data[i], LENGTH);
updateAmp();
curr_reverb = new ReverbCC( this );
return 0;
}
@ -212,6 +214,11 @@ void Mustang::updateAmp(void) {
}
void Mustang::updateReverb(void) {
// No-op for now
}
int Mustang::effect_toggle(int state_index, int state)
{
int ret, received;
@ -379,6 +386,64 @@ int Mustang::setAmp( int ord ) {
return ret;
}
int Mustang::setReverb( int ord ) {
int ret, received;
unsigned char scratch[LENGTH];
unsigned char *array;
switch (ord) {
case 1:
array = small_hall;
break;
case 2:
array = large_hall;
break;
case 3:
array = small_room;
break;
case 4:
array = large_room;
break;
case 5:
array = small_plate;
break;
case 6:
array = large_plate;
break;
case 7:
array = ambient;
break;
case 8:
array = arena;
break;
case 9:
array = spring_63;
break;
case 10:
array = spring_65;
break;
default:
fprintf( stderr, "W - Reverb select %d not supported\n", ord );
return 0;
}
array[FXSLOT] = curr_state[REVERB_STATE][FXSLOT];
// Setup amp personality
ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT);
libusb_interrupt_transfer(amp_hand, 0x81, scratch, LENGTH, &received, TMOUT);
ret = libusb_interrupt_transfer(amp_hand, 0x01, execute, LENGTH, &received, TMOUT);
libusb_interrupt_transfer(amp_hand, 0x81, scratch, LENGTH, &received, TMOUT);
// Copy to current setting store
memcpy(curr_state[REVERB_STATE], array, LENGTH);
updateReverb();
return ret;
}
int Mustang::save_on_amp(char *name, int slot)
{
int ret, received;
@ -406,6 +471,45 @@ int Mustang::save_on_amp(char *name, int slot)
return ret;
}
int Mustang::efx_common1(int parm, int bucket, int type, int value)
{
static unsigned short previous = 0;
int ret, received;
unsigned char array[LENGTH];
memset(array, 0x00, LENGTH);
array[0] = 0x05;
array[1] = 0xc3;
array[2] = 0x06;
array[3] = curr_state[type][EFFECT];
// target parameter
array[5] = array[6] = parm;
// bucket
array[7] = bucket;
// Scale and clamp to valid index range
int index = (int) ceil( (double)value * magic_scale_factor );
if ( index > magic_max ) index = magic_max;
unsigned short eff_value = magic_values[index];
// Try to prevent extra traffic if successive calls resolve to the same
// slot.
if (eff_value == previous) return 0;
previous = eff_value;
array[9] = eff_value & 0xff;
array[10] = (eff_value >> 8) & 0xff;
// Send command and flush reply
ret = libusb_interrupt_transfer(amp_hand, 0x01, array, LENGTH, &received, TMOUT);
libusb_interrupt_transfer(amp_hand, 0x81, array, LENGTH, &received, TMOUT);
return ret;
}
int Mustang::load_memory_bank( int slot )
{
int ret, received;

View file

@ -7,11 +7,10 @@
#include <string.h>
#include <unistd.h>
#include <libusb-1.0/libusb.h>
//#include <QtDebug>
#include "effects_enum.h"
#include "data_structs.h"
//#include <time.h>
#include "amp.h"
#include "reverb.h"
// amp's VID and PID
#define USB_VID 0x1ed8
@ -117,6 +116,18 @@
#define BRIT_WATT_ID 0xff
#define BRIT_COLOR_ID 0xfc
// Reverb id values
#define SM_HALL_ID 0x24
#define LG_HALL_ID 0x3a
#define SM_ROOM_ID 0x26
#define LG_ROOM_ID 0x3b
#define SM_PLATE_ID 0x4e
#define LG_PLATE_ID 0x4b
#define AMBIENT_ID 0x4c
#define ARENA_ID 0x4d
#define SPRING_63_ID 0x21
#define SPRING_65_ID 0x0b
class Mustang
{
public:
@ -126,6 +137,9 @@ public:
int stop_amp(void); // terminate communication
int set_effect(struct fx_pedal_settings);
int setAmp( int ord );
int setReverb( int ord );
int save_on_amp(char *, int);
int load_memory_bank(int);
int save_effects(int , char *, int , struct fx_pedal_settings *);
@ -136,7 +150,10 @@ public:
int control_common1(int parm, int bucket, int value);
int control_common2(int parm, int bucket, int value);
int efx_common1(int parm, int bucket, int type, int value);
AmpCC * getAmp( void ) { return curr_amp;}
ReverbCC * getReverb( void ) { return curr_reverb;}
private:
libusb_device_handle *amp_hand; // handle for USB communication
@ -166,8 +183,11 @@ public:
unsigned char curr_state[7][LENGTH];
AmpCC * curr_amp;
ReverbCC * curr_reverb;
void updateAmp(void);
void updateReverb(void);
};
#endif // MUSTANG_H

View file

@ -39,10 +39,11 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo
case 0xb0: {
// Control change
int rc;
int rc = 0;
int cc = (*message)[1];
int value = (*message)[2];
AmpCC *ampModel = mustang.getAmp();
ReverbCC *reverbModel = mustang.getReverb();
// Effects on/off
if ( cc >= 23 && cc <= 26 ) {
@ -53,6 +54,30 @@ void message_action( double deltatime, std::vector< unsigned char > *message, vo
else if ( value > 63 && value <= 127 ) state = 1;
rc = mustang.effect_toggle( index, state );
}
// Set reverb model
else if ( cc == 58 ) {
rc = mustang.setReverb( value );
}
// Level
else if ( cc == 59 ) {
rc = reverbModel->cc59( value );
}
// Decay
else if ( cc == 60 ) {
rc = reverbModel->cc60( value );
}
// Dwell
else if ( cc == 61 ) {
rc = reverbModel->cc61( value );
}
// Diffusion
else if ( cc == 62 ) {
rc = reverbModel->cc62( value );
}
// Tone
else if ( cc == 63 ) {
rc = reverbModel->cc63( value );
}
// Set amp model
else if ( cc == 68 ) {
// fprintf( stderr, "DEBUG: %d\n", value );

29
reverb.cpp Normal file
View file

@ -0,0 +1,29 @@
#include "reverb.h"
#include "mustang.h"
int
ReverbCC::cc59( int value ) {
return amp->efx_common1( 0x00, 0x0b, REVERB_STATE, value );
}
int
ReverbCC::cc60( int value ) {
return amp->efx_common1( 0x01, 0x0b, REVERB_STATE, value );
}
int
ReverbCC::cc61( int value ) {
return amp->efx_common1( 0x02, 0x0b, REVERB_STATE, value );
}
int
ReverbCC::cc62( int value ) {
return amp->efx_common1( 0x03, 0x0b, REVERB_STATE, value );
}
int
ReverbCC::cc63( int value ) {
return amp->efx_common1( 0x04, 0x0b, REVERB_STATE, value );
}

30
reverb.h Normal file
View file

@ -0,0 +1,30 @@
// -*-c++-*-
#ifndef _REVERB_H
#define _REVERB_H
class Mustang;
class ReverbCC {
protected:
Mustang * amp;
public:
ReverbCC( Mustang * theAmp ) : amp(theAmp) {}
// Level
int cc59( int value );
// Decay
int cc60( int value );
// Dwell
int cc61( int value );
// Diffusion
int cc62( int value );
// Tone
int cc63( int value );
};
#endif

74
reverb_defaults.h Normal file
View file

@ -0,0 +1,74 @@
// Default settings for Mustang III (original) reverb models
//
// This header is auto-generated from decoded pcap capture.
static unsigned char small_hall[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6e, 0x5d, 0x6e, 0x80, 0x91, 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 large_hall[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3a, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4f, 0x3e, 0x80, 0x05, 0xb0, 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 small_room[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x26, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0x80, 0x80, 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 large_room[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3b, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0x80, 0x80, 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 small_plate[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4e, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0x80, 0x80, 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 large_plate[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4b, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x38, 0x80, 0x91, 0x80, 0xb6, 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 ambient[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4c, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x80, 0x80, 0x80, 0x80, 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 arena[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4d, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x80, 0x80, 0x80, 0x80, 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 spring_63[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x21, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0x80, 0x80, 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 spring_65[] = {
0x1c, 0x03, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0b, 0x00, 0x05, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x8b, 0x49, 0xff, 0x80, 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
};