@ -9,7 +9,8 @@
# include "EEPROM.h"
const AppMode AppModeValues [ ] = { MUTE , NORMAL } ;
const int16_t CalibrationTolerance = 15 ;
const int16_t PitchCalibrationTolerance = 15 ;
const int16_t VolumeCalibrationTolerance = 21 ;
const int16_t PitchFreqOffset = 700 ;
const int16_t VolumeFreqOffset = 700 ;
const int8_t HYST_VAL = 40 ;
@ -42,8 +43,8 @@ static uint16_t old_midi_bend = 0;
static uint8_t midi_bend_low ;
static uint8_t midi_bend_high ;
static double double_log_freq = 0 ;
static double midi_key_follow = 0.5 ;
static uint32_t long_log_note = 0 ;
static uint32_t midi_key_follow = 2048 ; ;
// Configuration parameters
static uint8_t registerValue = 2 ;
@ -57,12 +58,12 @@ static uint8_t flag_pitch_bend_on = 1;
static uint8_t loop_midi_cc = 7 ;
static uint8_t rod_midi_cc = 255 ;
static uint8_t rod_midi_cc_lo = 255 ;
static double rod_cc_scale = 1 ;
static uint32_t rod_cc_scale = 128 ;
// tweakable paramameters
# 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 old_data_pot_value = 0 ;
@ -399,7 +400,7 @@ pitchfn1 = GetPitchMeasurement();
l_iteration_pitch = 0 ;
while ( ( abs ( pitchfn0 - pitchfn1 ) > CalibrationTolerance ) & & ( l_iteration_pitch < 12 ) )
while ( ( abs ( pitchfn0 - pitchfn1 ) > Pitch CalibrationTolerance) & & ( l_iteration_pitch < 12 ) )
{
SPImcpDAC2Asend ( pitchXn0 ) ;
@ -469,7 +470,7 @@ volumefn1 = GetVolumeMeasurement();
l_iteration_volume = 0 ;
while ( ( abs ( volumefn0 - volumefn1 ) > CalibrationTolerance ) & & ( l_iteration_volume < 12 ) )
while ( ( abs ( volumefn0 - volumefn1 ) > Volume CalibrationTolerance) & & ( l_iteration_volume < 12 ) )
{
SPImcpDAC2Bsend ( volumeXn0 ) ;
@ -496,6 +497,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 ) {
setWavetableSampleAdvance ( ( uint16_t ) ( hz * HZ_ADDVAL_FACTOR ) ) ;
}
@ -561,41 +632,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.
void Application : : midi_application ( )
{
double delta_loop_cc_val = 0 ;
double calculated_velocity = 0 ;
int16_t delta_loop_cc_val = 0 ;
int16_t calculated_velocity = 0 ;
// Calculate loop antena cc value for midi
new_midi_loop_cc_val = loop_hand_pos > > 1 ;
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
if ( ( vPointerIncrement < 18 ) | | ( vPointerIncrement > 65518 ) )
{
// Lowest note
double_log_freq = 0 ;
long_log_note = 0 ;
}
else if ( ( vPointerIncrement > 26315 ) & & ( vPointerIncrement < 39221 ) )
{
// Highest note
double_log_freq = 127 ;
long_log_note = 127 ;
}
else if ( vPointerIncrement < 32768 )
{
// Positive frequencies
// 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
{
// Negative frequencies
// 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
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
switch ( _midistate )
@ -637,7 +709,7 @@ void Application::midi_application ()
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
midi_key_follow = 0.5 ;
midi_key_follow = 2048 ;
// Calculate note and associated pitch bend
calculate_note_bend ( ) ;
@ -649,8 +721,8 @@ void Application::midi_application ()
// Calculate velocity
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 ) ;
midi_velocity = min ( round ( abs ( calculated_velocity ) ) , 127 ) ;
calculated_velocity = ( ( 127 - midi_volume_trigger ) > > 1 ) + ( VELOCITY_SENS * midi_volume_trigger * delta_loop_cc_val / midi_timer ) ;
midi_velocity = min ( abs ( calculated_velocity ) , 127 ) ;
}
else
{
@ -710,12 +782,12 @@ void Application::midi_application ()
if ( flag_legato_on = = 1 )
{
// 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
{
// Set key follow to max so as no key follows
midi_key_follow = 127 ;
midi_key_follow = 520 19 2; // 127*2^12
}
// Calculate note and associated pitch bend
@ -771,16 +843,16 @@ void Application::midi_application ()
void Application : : calculate_note_bend ( )
{
double double _log_bend;
double double _norm_log_bend;
int32_t long _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 ( ( abs ( double _log_bend) > = midi_key_follow ) & & ( midi_key_follow ! = 127 ) )
if ( ( abs ( long _log_bend) > = midi_key_follow ) & & ( midi_key_follow ! = 520 19 2) )
{
new_midi_note = round ( double_log_freq ) ; // Select the new midi chromatic note
double_log_bend = double_log_freq - new_midi_note ; // calculate bend to reach precise note played
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
long_log_bend = ( ( int32_t ) long_log_note ) - ( ( ( int32_t ) new_midi_note ) * 4096 ) ; // calculate bend to reach precise note played
}
else
{
@ -791,16 +863,16 @@ void Application::calculate_note_bend ()
if ( flag_pitch_bend_on = = 1 )
{
// use it to reach precise note played
double_norm_log_bend = ( double _log_bend / midi_bend_range ) ;
if ( double_norm_log_bend > 1 )
long_norm_log_bend = ( long _log_bend / midi_bend_range ) ;
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
{
@ -968,42 +1040,42 @@ void Application::set_parameters ()
case 0 :
rod_midi_cc = 255 ; // Nothing
rod_midi_cc_lo = 255 ; // Nothing
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
case 1 :
rod_midi_cc = 8 ; // Balance
rod_midi_cc_lo = 255 ; // No least significant bits
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
case 2 :
rod_midi_cc = 10 ; // Pan
rod_midi_cc_lo = 255 ; // No least significant bits
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
case 3 :
rod_midi_cc = 16 ; // General Purpose 1 (14 Bits)
rod_midi_cc_lo = 48 ; // General Purpose 1 least significant bits
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
case 4 :
rod_midi_cc = 17 ; // General Purpose 2 (14 Bits)
rod_midi_cc_lo = 49 ; // General Purpose 2 least significant bits
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
case 5 :
rod_midi_cc = 18 ; // General Purpose 3 (7 Bits)
rod_midi_cc_lo = 255 ; // No least significant bits
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
case 6 :
rod_midi_cc = 19 ; // General Purpose 4 (7 Bits)
rod_midi_cc_lo = 255 ; // No least significant bits
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
default :
rod_midi_cc = 74 ; // Cutoff (exists of both loop and rod)
rod_midi_cc_lo = 255 ; // No least significant bits
rod_cc_scale = 1.0 ;
rod_cc_scale = 128 ;
break ;
}
break ;