Update application.cpp

MrDham-remove-float-calc
MrDham 5 months ago committed by GitHub
parent 718822081c
commit af0b16f051
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 147
      Open_Theremin_V3/application.cpp

@ -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;

Loading…
Cancel
Save