|
|
@ -42,8 +42,8 @@ static uint16_t old_midi_bend = 0; |
|
|
|
static uint8_t midi_bend_low;
|
|
|
|
static uint8_t midi_bend_low;
|
|
|
|
static uint8_t midi_bend_high; |
|
|
|
static uint8_t midi_bend_high; |
|
|
|
|
|
|
|
|
|
|
|
static double double_log_freq = 0; |
|
|
|
static uint32_t long_log_note = 0; |
|
|
|
static double midi_key_follow = 0.5; |
|
|
|
static uint32_t midi_key_follow = 2048; ; |
|
|
|
|
|
|
|
|
|
|
|
// Configuration parameters
|
|
|
|
// Configuration parameters
|
|
|
|
static uint8_t registerValue = 2; |
|
|
|
static uint8_t registerValue = 2; |
|
|
@ -57,12 +57,12 @@ static uint8_t flag_pitch_bend_on = 1; |
|
|
|
static uint8_t loop_midi_cc = 7; |
|
|
|
static uint8_t loop_midi_cc = 7; |
|
|
|
static uint8_t rod_midi_cc = 255;
|
|
|
|
static uint8_t rod_midi_cc = 255;
|
|
|
|
static uint8_t rod_midi_cc_lo = 255;
|
|
|
|
static uint8_t rod_midi_cc_lo = 255;
|
|
|
|
static double rod_cc_scale = 1; |
|
|
|
static uint32_t rod_cc_scale = 128; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// tweakable paramameters
|
|
|
|
// tweakable paramameters
|
|
|
|
#define VELOCITY_SENS 9 // How easy it is to reach highest velocity (127). Something betwen 5 and 12.
|
|
|
|
#define VELOCITY_SENS 9 // How easy it is to reach highest velocity (127). Something betwen 5 and 12.
|
|
|
|
#define PLAYER_ACCURACY 0.2 // between 0 (very accurate players) and 0.5 (not accurate at all)
|
|
|
|
#define PLAYER_ACCURACY 819 // between 0 (very accurate players) and 2048 (not accurate at all)
|
|
|
|
|
|
|
|
|
|
|
|
static uint16_t data_pot_value = 0;
|
|
|
|
static uint16_t data_pot_value = 0;
|
|
|
|
static uint16_t old_data_pot_value = 0;
|
|
|
|
static uint16_t old_data_pot_value = 0;
|
|
|
@ -496,6 +496,76 @@ EEPROM.put(2,volumeXn0); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// calculate log2 of an unsigned from 1 to 65535 into a 4.12 fixed point unsigned
|
|
|
|
|
|
|
|
// To avoid use of log (double) function
|
|
|
|
|
|
|
|
uint16_t Application::log2U16 (uint16_t lin_input) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
uint32_t long_lin; // To turn input into a 16.16 fixed point
|
|
|
|
|
|
|
|
//unsigned long bit_pos;
|
|
|
|
|
|
|
|
uint32_t log_output; // 4.12 fixed point log calculation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int32_t long_x1; |
|
|
|
|
|
|
|
int32_t long_x2; |
|
|
|
|
|
|
|
int32_t long_x3; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int32_t POLY_A0 = 37;
|
|
|
|
|
|
|
|
const int32_t POLY_A1 = 46390;
|
|
|
|
|
|
|
|
const int32_t POLY_A2 = -18778;
|
|
|
|
|
|
|
|
const int32_t POLY_A3 = 5155;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lin_input != 0) |
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
long_lin = (uint32_t) (lin_input) << 16;
|
|
|
|
|
|
|
|
log_output = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate integer part of log2 and reduce long_lin into 16.16 between 1 and 2
|
|
|
|
|
|
|
|
if (long_lin >= 16777216) // 2^(8 + 16)
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log_output += 8 << 12; |
|
|
|
|
|
|
|
long_lin = long_lin >> 8;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (long_lin >= 1048576) // 2^(4 + 16)
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log_output += 4 << 12; |
|
|
|
|
|
|
|
long_lin = long_lin >> 4;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (long_lin >= 262144) // 2^(2 + 16)
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log_output += 2 << 12; |
|
|
|
|
|
|
|
long_lin = long_lin >> 2;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (long_lin >= 131072) // 2^(1 + 16)
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log_output += 1 << 12; |
|
|
|
|
|
|
|
long_lin = long_lin >> 1;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// long_lin is between 1 and 2 now (16.16 fixed point)
|
|
|
|
|
|
|
|
// Calculate 3rd degree polynomial approximation log(x)=Polynomial(x-1) in signed long s15.16 and reduce to unsigned 4.12 at the very end.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long_lin = long_lin >> 1; // reduce to 17.15 bit to support signed operations here after
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long_x1 = long_lin-(32768); //(x-1) we have the decimal part in s15 now
|
|
|
|
|
|
|
|
long_x2 = (long_x1 * long_x1) >> 15 ; // (x-1)^2
|
|
|
|
|
|
|
|
long_x3 = (long_x2 * long_x1) >> 15 ; // (x-1)^3
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log_output += ( (POLY_A0)
|
|
|
|
|
|
|
|
+ ((POLY_A1 * long_x1) >> 15)
|
|
|
|
|
|
|
|
+ ((POLY_A2 * long_x2) >> 15)
|
|
|
|
|
|
|
|
+ ((POLY_A3 * long_x3) >> 15) ) >> 3; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log_output=0;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return log_output;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void Application::hzToAddVal(float hz) { |
|
|
|
void Application::hzToAddVal(float hz) { |
|
|
|
setWavetableSampleAdvance((uint16_t)(hz * HZ_ADDVAL_FACTOR)); |
|
|
|
setWavetableSampleAdvance((uint16_t)(hz * HZ_ADDVAL_FACTOR)); |
|
|
|
} |
|
|
|
} |
|
|
@ -561,41 +631,42 @@ void Application::midi_msg_send(uint8_t channel, uint8_t midi_cmd1, uint8_t midi |
|
|
|
// The bigger is synth's pitch bend range the beter is the effect.
|
|
|
|
// The bigger is synth's pitch bend range the beter is the effect.
|
|
|
|
void Application::midi_application () |
|
|
|
void Application::midi_application () |
|
|
|
{ |
|
|
|
{ |
|
|
|
double delta_loop_cc_val = 0;
|
|
|
|
int16_t delta_loop_cc_val = 0;
|
|
|
|
double calculated_velocity = 0; |
|
|
|
int16_t calculated_velocity = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Calculate loop antena cc value for midi
|
|
|
|
// Calculate loop antena cc value for midi
|
|
|
|
new_midi_loop_cc_val = loop_hand_pos >> 1;
|
|
|
|
new_midi_loop_cc_val = loop_hand_pos >> 1;
|
|
|
|
new_midi_loop_cc_val = min (new_midi_loop_cc_val, 127); |
|
|
|
new_midi_loop_cc_val = min (new_midi_loop_cc_val, 127); |
|
|
|
delta_loop_cc_val = (double)new_midi_loop_cc_val - (double)old_midi_loop_cc_val; |
|
|
|
delta_loop_cc_val = (int16_t)new_midi_loop_cc_val - (int16_t)old_midi_loop_cc_val; |
|
|
|
|
|
|
|
|
|
|
|
// Calculate log freq
|
|
|
|
// Calculate log freq
|
|
|
|
if ((vPointerIncrement < 18) || (vPointerIncrement > 65518))
|
|
|
|
if ((vPointerIncrement < 18) || (vPointerIncrement > 65518))
|
|
|
|
{ |
|
|
|
{ |
|
|
|
// Lowest note
|
|
|
|
// Lowest note
|
|
|
|
double_log_freq = 0;
|
|
|
|
long_log_note = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
else if ((vPointerIncrement > 26315) && (vPointerIncrement < 39221)) |
|
|
|
else if ((vPointerIncrement > 26315) && (vPointerIncrement < 39221)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Highest note
|
|
|
|
// Highest note
|
|
|
|
double_log_freq = 127;
|
|
|
|
long_log_note = 127;
|
|
|
|
} |
|
|
|
} |
|
|
|
else if (vPointerIncrement < 32768) |
|
|
|
else if (vPointerIncrement < 32768) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Positive frequencies
|
|
|
|
// Positive frequencies
|
|
|
|
// Find note in the playing range
|
|
|
|
// Find note in the playing range
|
|
|
|
double_log_freq = (log (vPointerIncrement/17.152) / 0.057762265); // Precise note played in the logaritmic scale
|
|
|
|
// 16795 = log2U16 (C0 [8.1758] * HZ_ADDVAL_FACTOR [2.09785])
|
|
|
|
|
|
|
|
long_log_note = 12 * ((uint32_t) log2U16(vPointerIncrement) - 16795); // Precise note played in the logaritmic scale
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Negative frequencies
|
|
|
|
// Negative frequencies
|
|
|
|
// Find note in the playing range
|
|
|
|
// Find note in the playing range
|
|
|
|
double_log_freq = (log ((65535-vPointerIncrement+1)/17.152) / 0.057762265); // Precise note played in the logaritmic scale
|
|
|
|
// 16795 = log2U16 (C0 [8.1758] * HZ_ADDVAL_FACTOR [2.09785])
|
|
|
|
|
|
|
|
long_log_note = 12 * ((uint32_t) log2U16(65535-vPointerIncrement+1) - 16795); // Precise note played in the logaritmic scale
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Calculate rod antena cc value for midi
|
|
|
|
// Calculate rod antena cc value for midi
|
|
|
|
new_midi_rod_cc_val = round (min(((double_log_freq * 128) * rod_cc_scale), 16383)); // 14 bit value !
|
|
|
|
new_midi_rod_cc_val = (uint16_t) min((long_log_note * rod_cc_scale) >> 12, 16383); // 14 bit value
|
|
|
|
|
|
|
|
|
|
|
|
// State machine for MIDI
|
|
|
|
// State machine for MIDI
|
|
|
|
switch (_midistate) |
|
|
|
switch (_midistate) |
|
|
@ -637,7 +708,7 @@ void Application::midi_application () |
|
|
|
if (new_midi_loop_cc_val > midi_volume_trigger) |
|
|
|
if (new_midi_loop_cc_val > midi_volume_trigger) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Set key follow to the minimum in order to use closest note played as the center note
|
|
|
|
// Set key follow to the minimum in order to use closest note played as the center note
|
|
|
|
midi_key_follow = 0.5; |
|
|
|
midi_key_follow = 2048; |
|
|
|
|
|
|
|
|
|
|
|
// Calculate note and associated pitch bend
|
|
|
|
// Calculate note and associated pitch bend
|
|
|
|
calculate_note_bend (); |
|
|
|
calculate_note_bend (); |
|
|
@ -649,8 +720,8 @@ void Application::midi_application () |
|
|
|
// Calculate velocity
|
|
|
|
// Calculate velocity
|
|
|
|
if (midi_timer != 0) |
|
|
|
if (midi_timer != 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
calculated_velocity = (64 * (127 - (double)midi_volume_trigger) / 127) + (VELOCITY_SENS * (double)midi_volume_trigger * delta_loop_cc_val / (double)midi_timer); |
|
|
|
calculated_velocity = ((127 - midi_volume_trigger) >> 1 ) + (VELOCITY_SENS * midi_volume_trigger * delta_loop_cc_val / midi_timer); |
|
|
|
midi_velocity = min (round (abs (calculated_velocity)), 127); |
|
|
|
midi_velocity = min (abs (calculated_velocity), 127); |
|
|
|
} |
|
|
|
} |
|
|
|
else
|
|
|
|
else
|
|
|
|
{ |
|
|
|
{ |
|
|
@ -710,12 +781,12 @@ void Application::midi_application () |
|
|
|
if ( flag_legato_on == 1) |
|
|
|
if ( flag_legato_on == 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Set key follow so as next played note will be at limit of pitch bend range
|
|
|
|
// Set key follow so as next played note will be at limit of pitch bend range
|
|
|
|
midi_key_follow = (double)(midi_bend_range) - PLAYER_ACCURACY; |
|
|
|
midi_key_follow = ((uint32_t) midi_bend_range * 4096) - PLAYER_ACCURACY; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Set key follow to max so as no key follows
|
|
|
|
// Set key follow to max so as no key follows
|
|
|
|
midi_key_follow = 127; |
|
|
|
midi_key_follow = 520192; // 127*2^12
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Calculate note and associated pitch bend
|
|
|
|
// Calculate note and associated pitch bend
|
|
|
@ -771,16 +842,16 @@ void Application::midi_application () |
|
|
|
|
|
|
|
|
|
|
|
void Application::calculate_note_bend () |
|
|
|
void Application::calculate_note_bend () |
|
|
|
{ |
|
|
|
{ |
|
|
|
double double_log_bend; |
|
|
|
int32_t long_log_bend; |
|
|
|
double double_norm_log_bend; |
|
|
|
int32_t long_norm_log_bend; |
|
|
|
|
|
|
|
|
|
|
|
double_log_bend = double_log_freq - old_midi_note; // How far from last played midi chromatic note we are
|
|
|
|
long_log_bend = ((int32_t)long_log_note) - (((int32_t) old_midi_note) * 4096); // How far from last played midi chromatic note we are
|
|
|
|
|
|
|
|
|
|
|
|
// If too much far from last midi chromatic note played (midi_key_follow depends on pitch bend range)
|
|
|
|
// If too much far from last midi chromatic note played (midi_key_follow depends on pitch bend range)
|
|
|
|
if ((abs (double_log_bend) >= midi_key_follow) && (midi_key_follow != 127)) |
|
|
|
if ((abs (long_log_bend) >= midi_key_follow) && (midi_key_follow != 520192)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
new_midi_note = round (double_log_freq); // Select the new midi chromatic note
|
|
|
|
new_midi_note = (uint8_t) ((long_log_note + 2048) >> 12); // Select the new midi chromatic note - round to integer part by adding 1/2 before shifting
|
|
|
|
double_log_bend = double_log_freq - new_midi_note; // calculate bend to reach precise note played
|
|
|
|
long_log_bend = ((int32_t) long_log_note) - (((int32_t) new_midi_note) * 4096); // calculate bend to reach precise note played
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
@ -791,16 +862,16 @@ void Application::calculate_note_bend () |
|
|
|
if (flag_pitch_bend_on == 1) |
|
|
|
if (flag_pitch_bend_on == 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// use it to reach precise note played
|
|
|
|
// use it to reach precise note played
|
|
|
|
double_norm_log_bend = (double_log_bend / midi_bend_range); |
|
|
|
long_norm_log_bend = (long_log_bend / midi_bend_range); |
|
|
|
if (double_norm_log_bend > 1) |
|
|
|
if (long_norm_log_bend > 4096) |
|
|
|
{ |
|
|
|
{ |
|
|
|
double_norm_log_bend = 1;
|
|
|
|
long_norm_log_bend = 4096;
|
|
|
|
} |
|
|
|
} |
|
|
|
else if (double_norm_log_bend < -1) |
|
|
|
else if (long_norm_log_bend < -4096) |
|
|
|
{ |
|
|
|
{ |
|
|
|
double_norm_log_bend = -1; |
|
|
|
long_norm_log_bend = -4096;
|
|
|
|
} |
|
|
|
} |
|
|
|
new_midi_bend = 8192 + (8191 * double_norm_log_bend); // Calculate midi pitch bend
|
|
|
|
new_midi_bend = 8192 + ((long_norm_log_bend * 8191) >> 12); // Calculate midi pitch bend
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
@ -968,42 +1039,42 @@ void Application::set_parameters () |
|
|
|
case 0: |
|
|
|
case 0: |
|
|
|
rod_midi_cc = 255; // Nothing
|
|
|
|
rod_midi_cc = 255; // Nothing
|
|
|
|
rod_midi_cc_lo = 255; // Nothing
|
|
|
|
rod_midi_cc_lo = 255; // Nothing
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 1: |
|
|
|
case 1: |
|
|
|
rod_midi_cc = 8; // Balance
|
|
|
|
rod_midi_cc = 8; // Balance
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 2: |
|
|
|
case 2: |
|
|
|
rod_midi_cc = 10; // Pan
|
|
|
|
rod_midi_cc = 10; // Pan
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 3: |
|
|
|
case 3: |
|
|
|
rod_midi_cc = 16; // General Purpose 1 (14 Bits)
|
|
|
|
rod_midi_cc = 16; // General Purpose 1 (14 Bits)
|
|
|
|
rod_midi_cc_lo = 48; // General Purpose 1 least significant bits
|
|
|
|
rod_midi_cc_lo = 48; // General Purpose 1 least significant bits
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 4: |
|
|
|
case 4: |
|
|
|
rod_midi_cc = 17; // General Purpose 2 (14 Bits)
|
|
|
|
rod_midi_cc = 17; // General Purpose 2 (14 Bits)
|
|
|
|
rod_midi_cc_lo = 49; // General Purpose 2 least significant bits
|
|
|
|
rod_midi_cc_lo = 49; // General Purpose 2 least significant bits
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 5: |
|
|
|
case 5: |
|
|
|
rod_midi_cc = 18; // General Purpose 3 (7 Bits)
|
|
|
|
rod_midi_cc = 18; // General Purpose 3 (7 Bits)
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case 6: |
|
|
|
case 6: |
|
|
|
rod_midi_cc = 19; // General Purpose 4 (7 Bits)
|
|
|
|
rod_midi_cc = 19; // General Purpose 4 (7 Bits)
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default: |
|
|
|
default: |
|
|
|
rod_midi_cc = 74; // Cutoff (exists of both loop and rod)
|
|
|
|
rod_midi_cc = 74; // Cutoff (exists of both loop and rod)
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_midi_cc_lo = 255; // No least significant bits
|
|
|
|
rod_cc_scale = 1.0; |
|
|
|
rod_cc_scale = 128; |
|
|
|
break;
|
|
|
|
break;
|
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|