/*
MicroDexed
MicroDexed is a port of the Dexed sound engine
( https : //github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield.
Dexed ist heavily based on https : //github.com/google/music-synthesizer-for-android
( c ) 2018 - 2020 H . Wirtz < wirtz @ parasitstudio . de >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software Foundation ,
Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include <limits.h>
# include "config.h"
# include <Audio.h>
# include <Wire.h>
# include <MIDI.h>
# include <EEPROM.h>
# include <SD.h>
# include <SPI.h>
# include "midi_devices.hpp"
# include "dexed.h"
# include "dexed_sysex.h"
# include "effect_modulated_delay.h"
# include "effect_stereo_mono.h"
# include "effect_mono_stereo.h"
# include "PluginFx.h"
# include "UI.hpp"
# include "source_microdexed.h"
// Audio engines
AudioSourceMicroDexed * MicroDexed [ NUM_DEXED ] ;
AudioAmplifier * dexed_level [ NUM_DEXED ] ;
AudioEffectMonoStereo * mono2stereo [ NUM_DEXED ] ;
AudioAnalyzePeak microdexed_peak ;
AudioMixer4 microdexed_peak_mixer ;
AudioSynthWaveform chorus_modulator ;
AudioAmplifier modchorus_inverter ;
AudioMixer4 dexed_mixer_r ;
AudioMixer4 dexed_mixer_l ;
AudioMixer4 master_mixer_r ;
AudioMixer4 master_mixer_l ;
AudioAmplifier volume_r ;
AudioAmplifier volume_l ;
AudioEffectStereoMono stereo2mono ;
AudioAnalyzePeak master_peak_r ;
AudioAnalyzePeak master_peak_l ;
# if defined(USE_FX)
AudioMixer4 delay_send_mixer_r ;
AudioMixer4 delay_send_mixer_l ;
AudioMixer4 delay_fb_mixer_r ;
AudioMixer4 delay_fb_mixer_l ;
AudioEffectDelay delay_r ;
AudioEffectDelay delay_l ;
AudioMixer4 chorus_send_mixer_r ;
AudioMixer4 chorus_send_mixer_l ;
AudioEffectModulatedDelay modchorus_r ;
AudioEffectModulatedDelay modchorus_l ;
# if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT
AudioFilterBiquad modchorus_filter_r ;
AudioFilterBiquad modchorus_filter_l ;
# endif
AudioMixer4 reverb_send_mixer_r ;
AudioMixer4 reverb_send_mixer_l ;
AudioEffectFreeverb freeverb_l ;
AudioEffectFreeverb freeverb_r ;
# endif
# if defined(USE_FX)
// FX chain left
AudioConnection patchCord1 ( delay_send_mixer_l , 0 , delay_fb_mixer_l , 0 ) ;
AudioConnection patchCord2 ( delay_fb_mixer_l , delay_l ) ;
AudioConnection patchCord3 ( delay_l , 0 , delay_fb_mixer_l , 1 ) ; // feedback-loop
AudioConnection patchCord4 ( chorus_send_mixer_l , 0 , modchorus_l , 0 ) ;
AudioConnection patchCord5 ( chorus_modulator , 0 , modchorus_l , 1 ) ;
# if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT
AudioConnection patchCord6 ( modchorus_l , modchorus_filter_l ) ;
AudioConnection patchCord7 ( modchorus_filter_l , modchorus_inverter ) ;
# else
AudioConnection patchCord6 ( modchorus_l , modchorus_inverter ) ;
# endif
AudioConnection patchCord8 ( reverb_send_mixer_l , freeverb_l ) ;
// FX chain right
AudioConnection patchCord9 ( delay_send_mixer_r , 0 , delay_fb_mixer_r , 0 ) ;
AudioConnection patchCord10 ( delay_fb_mixer_r , delay_r ) ;
AudioConnection patchCord11 ( delay_r , 0 , delay_fb_mixer_r , 1 ) ; // feedback-loop
AudioConnection patchCord12 ( chorus_send_mixer_r , modchorus_r ) ;
AudioConnection patchCord13 ( chorus_modulator , 0 , modchorus_r , 1 ) ;
# if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT
AudioConnection patchCord14 ( modchorus_r , modchorus_filter_r ) ;
# endif
AudioConnection patchCord15 ( reverb_send_mixer_r , freeverb_r ) ;
# endif
# if defined(USE_FX)
// FX chain tail
AudioConnection patchCord16 ( delay_fb_mixer_r , 0 , master_mixer_r , DELAY ) ;
AudioConnection patchCord17 ( delay_fb_mixer_l , 0 , master_mixer_l , DELAY ) ;
# if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT
AudioConnection patchCord18 ( modchorus_filter_r , 0 , master_mixer_r , CHORUS ) ;
AudioConnection patchCord19 ( modchorus_inverter , 0 , master_mixer_l , CHORUS ) ;
# else
AudioConnection patchCord18 ( modchorus_r , 0 , master_mixer_r , CHORUS ) ;
AudioConnection patchCord19 ( modchorus_inverter , 0 , master_mixer_l , CHORUS ) ;
# endif
AudioConnection patchCord20 ( freeverb_r , 0 , master_mixer_r , REVERB ) ;
AudioConnection patchCord21 ( freeverb_l , 0 , master_mixer_l , REVERB ) ;
# endif
AudioConnection patchCord22 ( dexed_mixer_r , 0 , master_mixer_r , DEXED ) ;
AudioConnection patchCord23 ( dexed_mixer_l , 0 , master_mixer_l , DEXED ) ;
AudioConnection patchCord24 ( master_mixer_r , volume_r ) ;
AudioConnection patchCord25 ( master_mixer_l , volume_l ) ;
AudioConnection patchCord26 ( volume_r , 0 , stereo2mono , 0 ) ;
AudioConnection patchCord27 ( volume_l , 0 , stereo2mono , 1 ) ;
AudioConnection patchCord28 ( volume_r , master_peak_r ) ;
AudioConnection patchCord29 ( volume_l , master_peak_l ) ;
AudioConnection patchCord30 ( microdexed_peak_mixer , microdexed_peak ) ;
// Outputs
# ifdef AUDIO_DEVICE_USB
AudioOutputUSB usb1 ;
AudioConnection patchCord31 ( stereo2mono , 0 , usb1 , 0 ) ;
AudioConnection patchCord32 ( stereo2mono , 1 , usb1 , 1 ) ;
# endif
# if defined(TEENSY_AUDIO_BOARD)
AudioOutputI2S i2s1 ;
AudioConnection patchCord33 ( stereo2mono , 0 , i2s1 , 0 ) ;
AudioConnection patchCord34 ( stereo2mono , 1 , i2s1 , 1 ) ;
AudioControlSGTL5000 sgtl5000_1 ;
# elif defined (I2S_AUDIO_ONLY)
AudioOutputI2S i2s1 ;
AudioConnection patchCord33 ( stereo2mono , 0 , i2s1 , 0 ) ;
AudioConnection patchCord34 ( stereo2mono , 1 , i2s1 , 1 ) ;
# elif defined(TGA_AUDIO_BOARD)
AudioOutputI2S i2s1 ;
AudioConnection patchCord33 ( stereo2mono , 0 , i2s1 , 0 ) ;
AudioConnection patchCord34 ( stereo2mono , 1 , i2s1 , 1 ) ;
AudioControlWM8731master wm8731_1 ;
# elif defined(PT8211_AUDIO)
AudioOutputPT8211 pt8211_1 ;
AudioConnection patchCord33 ( stereo2mono , 0 , pt8211_1 , 0 ) ;
AudioConnection patchCord34 ( stereo2mono , 1 , pt8211_1 , 1 ) ;
# elif defined(TEENSY_DAC_SYMMETRIC)
AudioOutputAnalogStereo dacOut ;
AudioMixer4 invMixer ;
AudioConnection patchCord33 ( stereo2mono , 0 , dacOut , 0 ) ;
AudioConnection patchCord34 ( stereo2mono , 1 , invMixer , 0 ) ;
AudioConnection patchCord35 ( invMixer , 0 , dacOut , 1 ) ;
# else
AudioOutputAnalogStereo dacOut ;
AudioConnection patchCord33 ( stereo2mono , 0 , dacOut , 0 ) ;
AudioConnection patchCord34 ( stereo2mono , 1 , dacOut , 1 ) ;
# endif
//
// Dynamic patching of MicroDexed objects
//
uint8_t nDynamic = 0 ;
# if defined(USE_FX)
AudioConnection * dynamicConnections [ NUM_DEXED * 11 ] ;
# else
AudioConnection * dynamicConnections [ NUM_DEXED * 5 ] ;
# endif
void create_audio_connections ( AudioSourceMicroDexed & dexed , AudioEffectMonoStereo & mono2stereo , AudioAmplifier & dexed_level , uint8_t instance_id )
{
dynamicConnections [ nDynamic + + ] = new AudioConnection ( dexed , 0 , microdexed_peak_mixer , instance_id ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( dexed , 0 , dexed_level , 0 ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( dexed_level , 0 , mono2stereo , 0 ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 0 , dexed_mixer_r , instance_id ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 1 , dexed_mixer_l , instance_id ) ;
# if defined(USE_FX)
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 0 , chorus_send_mixer_r , instance_id ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 1 , chorus_send_mixer_l , instance_id ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 0 , delay_send_mixer_r , instance_id ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 1 , delay_send_mixer_l , instance_id ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 0 , reverb_send_mixer_r , instance_id ) ;
dynamicConnections [ nDynamic + + ] = new AudioConnection ( mono2stereo , 1 , reverb_send_mixer_l , instance_id ) ;
# endif
}
uint8_t sd_card = 0 ;
Sd2Card card ;
SdVolume volume ;
uint8_t max_loaded_banks = 0 ;
char bank_name [ NUM_DEXED ] [ BANK_NAME_LEN ] ;
char voice_name [ NUM_DEXED ] [ VOICE_NAME_LEN ] ;
char bank_names [ NUM_DEXED ] [ MAX_BANKS ] [ BANK_NAME_LEN ] ;
char voice_names [ NUM_DEXED ] [ MAX_VOICES ] [ VOICE_NAME_LEN ] ;
uint8_t dexed_setup_number = 1 ;
elapsedMillis autostore ;
uint8_t midi_timing_counter = 0 ; // 24 per qarter
elapsedMillis midi_timing_timestep ;
uint16_t midi_timing_quarter = 0 ;
elapsedMillis long_button_pressed ;
//elapsedMicros fill_audio_buffer;
elapsedMillis control_rate ;
uint8_t active_voices [ NUM_DEXED ] ;
# ifdef SHOW_CPU_LOAD_MSEC
elapsedMillis cpu_mem_millis ;
# endif
uint32_t cpumax = 0 ;
elapsedMillis cpu_overload_throttle_timer ;
uint32_t peak_dexed = 0 ;
float peak_dexed_value = 0.0 ;
uint32_t peak_r = 0 ;
uint32_t peak_l = 0 ;
bool eeprom_update_flag = false ;
config_t configuration ;
uint8_t selected_dexed_instance = 0 ;
const uint8_t cs_pins [ ] = { SDCARD_TEENSY_CS_PIN , SDCARD_AUDIO_CS_PIN } ;
const uint8_t mosi_pins [ ] = { SDCARD_TEENSY_MOSI_PIN , SDCARD_AUDIO_MOSI_PIN } ;
const uint8_t sck_pins [ ] = { SDCARD_TEENSY_SCK_PIN , SDCARD_AUDIO_SCK_PIN } ;
char version_string [ LCD_cols + 1 ] ;
char sd_string [ LCD_cols + 1 ] ;
# if defined(USE_FX)
// Allocate the delay lines for chorus
int16_t delayline_r [ MOD_DELAY_SAMPLE_BUFFER ] ;
int16_t delayline_l [ MOD_DELAY_SAMPLE_BUFFER ] ;
# endif
# ifdef ENABLE_LCD_UI
/***********************************************************************
LCDMenuLib2
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
extern LCDMenuLib2 LCDML ;
extern uint8_t menu_state ;
# endif
void setup ( )
{
// Start audio system
AudioNoInterrupts ( ) ;
AudioMemory ( AUDIO_MEM ) ;
# ifdef DISPLAY_LCD_SPI
pinMode ( SDCARD_CS_PIN , OUTPUT ) ;
pinMode ( U8X8_CS_PIN , OUTPUT ) ;
# endif
# ifdef ENABLE_LCD_UI
setup_ui ( ) ;
# endif
# ifdef DEBUG
# ifdef ENABLE_LCD_UI
setup_debug_message ( ) ;
# endif
Serial . begin ( SERIAL_SPEED ) ;
# endif
# ifndef ENABLE_LCD_UI
# ifdef DEBUG
Serial . println ( F ( " NO LCD DISPLAY ENABLED! " ) ) ;
# endif
# endif
# ifdef DEBUG
generate_version_string ( version_string , sizeof ( version_string ) ) ;
Serial . println ( F ( " MicroDexed based on https://github.com/asb2m10/dexed " ) ) ;
Serial . println ( F ( " (c)2018-2020 H. Wirtz <wirtz@parasitstudio.de> " ) ) ;
Serial . println ( F ( " https://codeberg.org/dcoredump/MicroDexed " ) ) ;
Serial . print ( F ( " Version: " ) ) ;
Serial . println ( version_string ) ;
Serial . print ( F ( " CPU-Speed: " ) ) ;
Serial . print ( F_CPU / 1000000.0 , 1 ) ;
Serial . println ( F ( " MHz " ) ) ;
Serial . println ( F ( " <setup start> " ) ) ;
Serial . flush ( ) ;
# endif
setup_midi_devices ( ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( instance_id < MAX_DEXED )
{
# ifdef DEBUG
Serial . print ( F ( " Creating MicroDexed instance " ) ) ;
Serial . println ( instance_id , DEC ) ;
# endif
MicroDexed [ instance_id ] = new AudioSourceMicroDexed ( SAMPLE_RATE ) ;
dexed_level [ instance_id ] = new AudioAmplifier ( ) ;
mono2stereo [ instance_id ] = new AudioEffectMonoStereo ( ) ;
create_audio_connections ( * MicroDexed [ instance_id ] , * mono2stereo [ instance_id ] , * dexed_level [ instance_id ] , instance_id ) ;
}
else
{
# ifdef DEBUG
Serial . print ( F ( " Ignoring instance " ) ) ;
Serial . print ( instance_id , DEC ) ;
Serial . print ( F ( " (maximum allowed: " ) ) ;
Serial . print ( MAX_DEXED , DEC ) ;
Serial . println ( F ( " ) " ) ) ;
# endif
}
}
/*
// Init EEPROM if both buttons are pressed at startup
if ( digitalRead ( BUT_R_PIN ) = = HIGH & & digitalRead ( BUT_L_PIN ) = = HIGH )
{
# ifdef DEBUG
Serial . println ( F ( " Init EEPROM " ) ) ;
# endif
lcd . clear ( ) ;
lcd . setCursor ( 0 , 0 ) ;
lcd . print ( F ( " INIT " ) ) ;
lcd . setCursor ( 0 , 1 ) ;
lcd . print ( F ( " EEPROM " ) ) ;
initial_values_from_eeprom ( true ) ;
delay ( 2000 ) ;
}
else
initial_values_from_eeprom ( false ) ;
*/
initial_values_from_eeprom ( false ) ;
# if defined(TEENSY_AUDIO_BOARD)
sgtl5000_1 . enable ( ) ;
sgtl5000_1 . lineOutLevel ( SGTL5000_LINEOUT_LEVEL ) ;
sgtl5000_1 . dacVolumeRamp ( ) ;
sgtl5000_1 . dacVolume ( 1.0 ) ;
//sgtl5000_1.dacVolumeRampLinear();
//sgtl5000_1.dacVolumeRampDisable();
sgtl5000_1 . unmuteHeadphone ( ) ;
sgtl5000_1 . unmuteLineout ( ) ;
sgtl5000_1 . volume ( SGTL5000_HEADPHONE_VOLUME , SGTL5000_HEADPHONE_VOLUME ) ; // Headphone volume
//sgtl5000_1.audioPostProcessorEnable();
//sgtl5000_1.autoVolumeControl(1, 1, 1, 0.9, 0.01, 0.05);
//sgtl5000_1.autoVolumeEnable();
sgtl5000_1 . autoVolumeDisable ( ) ;
//sgtl5000_1.surroundSoundEnable();
sgtl5000_1 . surroundSoundDisable ( ) ;
//sgtl5000_1.surroundSound(7, 2); // Configures virtual surround width from 0 (mono) to 7 (widest). select may be set to 1 (disable), 2 (mono input) or 3 (stereo input).
//sgtl5000_1.enhanceBassEnable();
sgtl5000_1 . enhanceBassDisable ( ) ;
//sgtl5000_1.enhanceBass(1.0, 0.2, 1, 2); // Configures the bass enhancement by setting the levels of the original stereo signal and the bass-enhanced mono level which will be mixed together. The high-pass filter may be enabled (0) or bypassed (1).
/* The cutoff frequency is specified as follows:
value frequency
0 80 Hz
1 100 Hz
2 125 Hz
3 150 Hz
4 175 Hz
5 200 Hz
6 225 Hz
*/
//sgtl5000_1.eqBands(bass, mid_bass, midrange, mid_treble, treble);
# ifdef DEBUG
Serial . println ( F ( " Teensy-Audio-Board enabled. " ) ) ;
# endif
# elif defined(TGA_AUDIO_BOARD)
wm8731_1 . enable ( ) ;
wm8731_1 . volume ( 1.0 ) ;
# ifdef DEBUG
Serial . println ( F ( " TGA board enabled. " ) ) ;
# endif
# elif defined(I2S_AUDIO_ONLY)
# ifdef DEBUG
Serial . println ( F ( " I2S enabled. " ) ) ;
# endif
# elif defined(PT8211_AUDIO)
# ifdef DEBUG
Serial . println ( F ( " PT8211 enabled. " ) ) ;
# endif
# elif defined(TEENSY_DAC_SYMMETRIC)
invMixer . gain ( 0 , - 1.f ) ;
# ifdef DEBUG
Serial . println ( F ( " Internal DAC using symmetric outputs enabled. " ) ) ;
# endif
# else
# ifdef DEBUG
Serial . println ( F ( " Internal DAC enabled. " ) ) ;
# endif
# endif
// start SD card
# ifdef DISPLAY_LCD_SPI
change_disp_sd ( false ) ;
# endif
sd_card = check_sd_cards ( ) ;
if ( sd_card < 1 )
{
# ifdef DEBUG
Serial . println ( F ( " SD card not accessable. " ) ) ;
# endif
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
strcpy ( bank_name [ instance_id ] , " Default " ) ;
strcpy ( voice_name [ instance_id ] , " Default " ) ;
}
}
else
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
// read all bank names
max_loaded_banks = get_bank_names ( instance_id ) ;
strip_extension ( bank_names [ instance_id ] [ configuration . dexed [ instance_id ] . bank ] , bank_name [ instance_id ] ) ;
// read all voice name for actual bank
get_voice_names_from_bank ( configuration . dexed [ instance_id ] . bank , instance_id ) ;
# ifdef DEBUG
Serial . print ( F ( " Bank [ " ) ) ;
Serial . print ( bank_names [ instance_id ] [ configuration . dexed [ instance_id ] . bank ] ) ;
Serial . print ( F ( " / " ) ) ;
Serial . print ( bank_name [ instance_id ] ) ;
Serial . println ( F ( " ] " ) ) ;
for ( uint8_t n = 0 ; n < MAX_VOICES - 1 ; n + + )
{
if ( n < 10 )
Serial . print ( F ( " " ) ) ;
Serial . print ( F ( " " ) ) ;
Serial . print ( n , DEC ) ;
Serial . print ( F ( " [ " ) ) ;
Serial . print ( voice_names [ instance_id ] [ n ] ) ;
Serial . println ( F ( " ] " ) ) ;
}
# endif
// load default SYSEX data
load_sysex ( configuration . dexed [ instance_id ] . bank , configuration . dexed [ instance_id ] . voice , instance_id ) ;
}
}
# ifdef DISPLAY_LCD_SPI
change_disp_sd ( true ) ;
# endif
# if defined(USE_FX)
// Init effects
memset ( delayline_r , 0 , sizeof ( delayline_r ) ) ;
if ( ! modchorus_r . begin ( delayline_r , MOD_DELAY_SAMPLE_BUFFER ) ) {
# ifdef DEBUG
Serial . println ( F ( " AudioEffectModulatedDelay - begin failed (R) " ) ) ;
# endif
while ( 1 ) ;
}
memset ( delayline_l , 0 , sizeof ( delayline_l ) ) ;
if ( ! modchorus_l . begin ( delayline_l , MOD_DELAY_SAMPLE_BUFFER ) ) {
# ifdef DEBUG
Serial . println ( F ( " AudioEffectModulatedDelay - begin failed (L) " ) ) ;
# endif
while ( 1 ) ;
}
# ifdef DEBUG
Serial . print ( F ( " MOD_DELAY_SAMPLE_BUFFER= " ) ) ;
Serial . print ( MOD_DELAY_SAMPLE_BUFFER , DEC ) ;
Serial . println ( F ( " samples " ) ) ;
# endif
# endif
master_mixer_r . gain ( DEXED , 1.0 ) ;
master_mixer_l . gain ( DEXED , 1.0 ) ;
master_mixer_r . gain ( CHORUS , mapfloat ( configuration . chorus_level , CHORUS_LEVEL_MIN , CHORUS_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( CHORUS , mapfloat ( configuration . chorus_level , CHORUS_LEVEL_MIN , CHORUS_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_r . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_r . gain ( REVERB , mapfloat ( configuration . reverb_level , REVERB_LEVEL_MIN , REVERB_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( REVERB , mapfloat ( configuration . reverb_level , REVERB_LEVEL_MIN , REVERB_LEVEL_MAX , 0.0 , 1.0 ) ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
// INIT PEAK MIXER
microdexed_peak_mixer . gain ( instance_id , 1.0 ) ;
// INIT DEXED MIXER
dexed_mixer_r . gain ( instance_id , 1.0 ) ;
dexed_mixer_l . gain ( instance_id , 1.0 ) ;
# if defined(USE_FX)
// INIT REVERB
reverb_send_mixer_r . gain ( instance_id , mapfloat ( configuration . dexed [ instance_id ] . reverb_send , REVERB_SEND_MIN , REVERB_SEND_MAX , 0.0 , 1.0 ) ) ;
reverb_send_mixer_l . gain ( instance_id , mapfloat ( configuration . dexed [ instance_id ] . reverb_send , REVERB_SEND_MIN , REVERB_SEND_MAX , 0.0 , 1.0 ) ) ;
// INIT DELAY
delay_send_mixer_r . gain ( instance_id , mapfloat ( configuration . dexed [ instance_id ] . delay_send , DELAY_SEND_MIN , DELAY_SEND_MAX , 0.0 , 1.0 ) ) ;
delay_send_mixer_l . gain ( instance_id , mapfloat ( configuration . dexed [ instance_id ] . delay_send , DELAY_SEND_MIN , DELAY_SEND_MAX , 0.0 , 1.0 ) ) ;
// INIT CHORUS
chorus_send_mixer_r . gain ( instance_id , mapfloat ( configuration . dexed [ instance_id ] . chorus_send , CHORUS_SEND_MIN , CHORUS_SEND_MAX , 0.0 , 1.0 ) ) ;
chorus_send_mixer_l . gain ( instance_id , mapfloat ( configuration . dexed [ instance_id ] . chorus_send , CHORUS_SEND_MIN , CHORUS_SEND_MAX , 0.0 , 1.0 ) ) ;
// DEXED FILTER
//MicroDexed[instance_id]->fx.Gain = mapfloat(configuration.dexed[instance_id].sound_intensity, SOUND_INTENSITY_MIN, SOUND_INTENSITY_MAX, 0.0, SOUND_INTENSITY_AMP_MAX);
MicroDexed [ instance_id ] - > fx . Gain = 1.0 ;
MicroDexed [ instance_id ] - > fx . Reso = mapfloat ( configuration . dexed [ instance_id ] . filter_resonance , FILTER_RESONANCE_MIN , FILTER_RESONANCE_MAX , 1.0 , 0.0 ) ;
MicroDexed [ instance_id ] - > fx . Cutoff = mapfloat ( configuration . dexed [ instance_id ] . filter_cutoff , FILTER_CUTOFF_MIN , FILTER_CUTOFF_MAX , 1.0 , 0.0 ) ;
MicroDexed [ instance_id ] - > doRefreshVoice ( ) ;
# endif
// Dexed output level
dexed_level [ instance_id ] - > gain ( mapfloat ( configuration . dexed [ instance_id ] . sound_intensity , SOUND_INTENSITY_MIN , SOUND_INTENSITY_MAX , 0.0 , SOUND_INTENSITY_AMP_MAX ) ) ;
// PANORAMA
mono2stereo [ instance_id ] - > panorama ( mapfloat ( configuration . dexed [ instance_id ] . pan , PANORAMA_MIN , PANORAMA_MAX , - 1.0 , 1.0 ) ) ;
}
# if defined(USE_FX)
// DELAY
delay_r . delay ( 0 , mapfloat ( configuration . delay_time * 10 , DELAY_TIME_MIN , DELAY_TIME_MAX , 0.0 , float ( DELAY_TIME_MAX ) ) ) ;
delay_l . delay ( 0 , mapfloat ( configuration . delay_time * 10 , DELAY_TIME_MIN , DELAY_TIME_MAX , 0.0 , float ( DELAY_TIME_MAX ) ) ) ;
// delay_fb_mixer is the feedback-adding mixer
delay_fb_mixer_r . gain ( 0 , 1.0 ) ; // original signal
delay_fb_mixer_r . gain ( 1 , mapfloat ( configuration . delay_feedback , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX , 0.0 , 1.0 ) ) ; // amount of feedback
delay_fb_mixer_l . gain ( 0 , 1.0 ) ; // original signal
delay_fb_mixer_l . gain ( 1 , mapfloat ( configuration . delay_feedback , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX , 0.0 , 1.0 ) ) ; // amount of feedback
// CHORUS
switch ( configuration . chorus_waveform )
{
case 0 :
chorus_modulator . begin ( WAVEFORM_TRIANGLE ) ;
break ;
case 1 :
chorus_modulator . begin ( WAVEFORM_SINE ) ;
break ;
default :
chorus_modulator . begin ( WAVEFORM_TRIANGLE ) ;
}
chorus_modulator . phase ( 0 ) ;
chorus_modulator . frequency ( configuration . chorus_frequency / 10.0 ) ;
chorus_modulator . amplitude ( mapfloat ( configuration . chorus_depth , CHORUS_DEPTH_MIN , CHORUS_DEPTH_MAX , 0.0 , 1.0 ) ) ;
chorus_modulator . offset ( 0.0 ) ;
# if MOD_FILTER_OUTPUT == MOD_BUTTERWORTH_FILTER_OUTPUT
// Butterworth filter, 12 db/octave
modchorus_filter_r . setLowpass ( 0 , MOD_FILTER_CUTOFF_HZ , 0.707 ) ;
modchorus_filter_l . setLowpass ( 0 , MOD_FILTER_CUTOFF_HZ , 0.707 ) ;
# elif MOD_FILTER_OUTPUT == MOD_LINKWITZ_RILEY_FILTER_OUTPUT
// Linkwitz-Riley filter, 48 dB/octave
modchorus_filter_r . setLowpass ( 0 , MOD_FILTER_CUTOFF_HZ , 0.54 ) ;
modchorus_filter_r . setLowpass ( 1 , MOD_FILTER_CUTOFF_HZ , 1.3 ) ;
modchorus_filter_r . setLowpass ( 2 , MOD_FILTER_CUTOFF_HZ , 0.54 ) ;
modchorus_filter_r . setLowpass ( 3 , MOD_FILTER_CUTOFF_HZ , 1.3 ) ;
modchorus_filter_l . setLowpass ( 0 , MOD_FILTER_CUTOFF_HZ , 0.54 ) ;
modchorus_filter_l . setLowpass ( 1 , MOD_FILTER_CUTOFF_HZ , 1.3 ) ;
modchorus_filter_l . setLowpass ( 2 , MOD_FILTER_CUTOFF_HZ , 0.54 ) ;
modchorus_filter_l . setLowpass ( 3 , MOD_FILTER_CUTOFF_HZ , 1.3 ) ;
# endif
// REVERB
freeverb_r . roomsize ( mapfloat ( configuration . reverb_roomsize , REVERB_ROOMSIZE_MIN , REVERB_ROOMSIZE_MAX , 0.0 , 1.0 ) ) ;
freeverb_r . damping ( mapfloat ( configuration . reverb_damping , REVERB_DAMPING_MIN , REVERB_DAMPING_MAX , 0.0 , 1.0 ) ) ;
freeverb_l . roomsize ( mapfloat ( configuration . reverb_roomsize , REVERB_ROOMSIZE_MIN , REVERB_ROOMSIZE_MAX , 0.0 , 1.0 ) ) ;
freeverb_l . damping ( mapfloat ( configuration . reverb_damping , REVERB_DAMPING_MIN , REVERB_DAMPING_MAX , 0.0 , 1.0 ) ) ;
# endif
// MONO/STEREO
if ( configuration . mono = = 0 )
modchorus_inverter . gain ( - 1.0 ) ; // stereo mode
else
modchorus_inverter . gain ( 1.0 ) ; // mono mode
// set initial volume
set_volume ( configuration . vol , configuration . mono ) ;
// Initialize processor and memory measurements
AudioProcessorUsageMaxReset ( ) ;
AudioMemoryUsageMaxReset ( ) ;
# ifdef DEBUG
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
Serial . print ( F ( " Dexed instance " ) ) ;
Serial . print ( instance_id ) ;
Serial . println ( F ( " : " ) ) ;
Serial . print ( F ( " Bank/Voice from EEPROM [ " ) ) ;
Serial . print ( configuration . dexed [ instance_id ] . bank , DEC ) ;
Serial . print ( F ( " / " ) ) ;
Serial . print ( configuration . dexed [ instance_id ] . voice , DEC ) ;
Serial . println ( F ( " ] " ) ) ;
Serial . print ( F ( " Polyphony: " ) ) ;
Serial . println ( configuration . dexed [ instance_id ] . polyphony , DEC ) ;
//show_patch(instance_id);
}
Serial . print ( F ( " AUDIO_BLOCK_SAMPLES= " ) ) ;
Serial . print ( AUDIO_BLOCK_SAMPLES ) ;
Serial . print ( F ( " (Time per block= " ) ) ;
Serial . print ( 1000000 / ( SAMPLE_RATE / AUDIO_BLOCK_SAMPLES ) ) ;
Serial . println ( F ( " ms) " ) ) ;
# endif
# if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
show_cpu_and_mem_usage ( ) ;
# endif
AudioInterrupts ( ) ;
# ifdef DEBUG
Serial . println ( F ( " <setup end> " ) ) ;
# endif
}
void loop ( )
{
// MIDI input handling
check_midi_devices ( ) ;
// check encoder
ENCODER [ ENC_L ] . update ( ) ;
ENCODER [ ENC_R ] . update ( ) ;
// CONTROL-RATE-EVENT-HANDLING
if ( control_rate > CONTROL_RATE_MS )
{
control_rate = 0 ;
# ifdef ENABLE_LCD_UI
// LCD Menu
LCDML . loop ( ) ;
// initial starts voice selection menu as default
if ( menu_state = = MENU_START )
{
menu_state = MENU_VOICE ;
UI_func_voice_selection ( 0 ) ;
}
# endif
// EEPROM update handling
if ( autostore > = AUTOSTORE_MS & & eeprom_update_flag = = true )
{
// only store configuration data to EEPROM when AUTOSTORE_MS is reached and no voices are activated anymore
eeprom_update ( ) ;
}
// check for value changes, unused voices and CPU overload
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
active_voices [ instance_id ] = MicroDexed [ instance_id ] - > getNumNotesPlaying ( ) ;
# if defined(CPU_OVERLOAD_THROTTLE)
if ( AudioProcessorUsageMax ( ) > CPU_OVERLOAD_THROTTLE & & cpu_overload_throttle_timer > = CPU_OVERLOAD_THROTTLE_TIMER )
{
cpu_overload_throttle_timer = 0 ;
AudioProcessorUsageMaxReset ( ) ;
MicroDexed [ instance_id ] - > keyup ( - 1 ) ; // kills the oldest note and decreases max_notes
# ifdef DEBUG
Serial . print ( F ( " !!!CPU overload!!! Automatic throttling polyphony down to " ) ) ;
Serial . print ( MicroDexed [ instance_id ] - > getMaxNotes ( ) , DEC ) ;
Serial . print ( F ( " for instance " ) ) ;
Serial . print ( instance_id , DEC ) ;
Serial . println ( F ( " . " ) ) ;
# endif
configuration . dexed [ instance_id ] . polyphony = MicroDexed [ instance_id ] - > getMaxNotes ( ) ;
eeprom_update ( ) ; // useful to do this???
}
# endif
}
}
else
yield ( ) ;
# if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
if ( cpu_mem_millis > = SHOW_CPU_LOAD_MSEC )
{
if ( master_peak_r . available ( ) )
if ( master_peak_r . read ( ) = = 1.0 )
peak_r + + ;
if ( master_peak_l . available ( ) )
if ( master_peak_l . read ( ) = = 1.0 )
peak_l + + ;
if ( microdexed_peak . available ( ) )
{
peak_dexed_value = microdexed_peak . read ( ) ;
if ( peak_dexed_value > 0.99 )
peak_dexed + + ;
}
cpu_mem_millis - = SHOW_CPU_LOAD_MSEC ;
show_cpu_and_mem_usage ( ) ;
}
# endif
//}
}
/******************************************************************************
MIDI MESSAGE HANDLER
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void handleNoteOn ( byte inChannel , byte inNumber , byte inVelocity )
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( checkMidiChannel ( inChannel , instance_id ) )
{
if ( inNumber > = configuration . dexed [ instance_id ] . lowest_note & & inNumber < = configuration . dexed [ instance_id ] . highest_note )
MicroDexed [ instance_id ] - > keydown ( inNumber , uint8_t ( float ( configuration . dexed [ instance_id ] . velocity_level / 127.0 ) * inVelocity + 0.5 ) ) ;
}
}
}
void handleNoteOff ( byte inChannel , byte inNumber , byte inVelocity )
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( checkMidiChannel ( inChannel , instance_id ) )
{
if ( inNumber > = configuration . dexed [ instance_id ] . lowest_note & & inNumber < = configuration . dexed [ instance_id ] . highest_note )
MicroDexed [ instance_id ] - > keyup ( inNumber ) ;
}
}
}
void handleControlChange ( byte inChannel , byte inCtrl , byte inValue )
{
inCtrl = constrain ( inCtrl , 0 , 127 ) ;
inValue = constrain ( inValue , 0 , 127 ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( checkMidiChannel ( inChannel , instance_id ) )
{
# ifdef DEBUG
Serial . print ( F ( " INSTANCE " ) ) ;
Serial . print ( instance_id , DEC ) ;
Serial . print ( F ( " : CC# " ) ) ;
Serial . print ( inCtrl , DEC ) ;
Serial . print ( F ( " : " ) ) ;
Serial . println ( inValue , DEC ) ;
# endif
switch ( inCtrl ) {
case 0 :
if ( inValue < MAX_BANKS - 1 )
{
configuration . dexed [ instance_id ] . bank = inValue ;
eeprom_write ( ) ;
}
break ;
case 1 :
# ifdef DEBUG
Serial . println ( F ( " MODWHEEL CC " ) ) ;
# endif
MicroDexed [ instance_id ] - > controllers . modwheel_cc = inValue ;
MicroDexed [ instance_id ] - > controllers . refresh ( ) ;
break ;
case 2 :
# ifdef DEBUG
Serial . println ( F ( " BREATH CC " ) ) ;
# endif
MicroDexed [ instance_id ] - > controllers . breath_cc = inValue ;
//MicroDexed[instance_id]->controllers.breath_cc = 100 – BCrange + Output * BCrange * Bcvalue/100
MicroDexed [ instance_id ] - > controllers . refresh ( ) ;
break ;
case 4 :
# ifdef DEBUG
Serial . println ( F ( " FOOT CC " ) ) ;
# endif
MicroDexed [ instance_id ] - > controllers . foot_cc = inValue ;
MicroDexed [ instance_id ] - > controllers . refresh ( ) ;
break ;
case 5 : // Portamento time
configuration . dexed [ instance_id ] . portamento_time = inValue ;
MicroDexed [ instance_id ] - > setPortamentoMode ( configuration . dexed [ instance_id ] . portamento_mode , configuration . dexed [ instance_id ] . portamento_glissando , configuration . dexed [ instance_id ] . portamento_time ) ;
eeprom_write ( ) ;
break ;
case 7 : // Instance Volume
# ifdef DEBUG
Serial . println ( F ( " VOLUME CC " ) ) ;
# endif
configuration . dexed [ instance_id ] . sound_intensity = map ( inValue , 0 , 0x7f , SOUND_INTENSITY_MIN , SOUND_INTENSITY_MAX ) ;
# ifdef USE_FX
MicroDexed [ instance_id ] - > fx . Gain = mapfloat ( configuration . dexed [ instance_id ] . sound_intensity , SOUND_INTENSITY_MIN , SOUND_INTENSITY_MAX , 0.0 , SOUND_INTENSITY_AMP_MAX ) ;
# else
dexed_level [ instance_id ] - > gain ( mapfloat ( configuration . dexed [ instance_id ] . sound_intensity , SOUND_INTENSITY_MIN , SOUND_INTENSITY_MAX , 0.0 , SOUND_INTENSITY_AMP_MAX ) ) ;
# endif
eeprom_write ( ) ;
break ;
case 10 : // Pan
# ifdef DEBUG
Serial . println ( F ( " PANORAMA CC " ) ) ;
# endif
configuration . dexed [ instance_id ] . pan = map ( inValue , 0 , 0x7f , PANORAMA_MIN , PANORAMA_MAX ) ;
mono2stereo [ instance_id ] - > panorama ( mapfloat ( configuration . dexed [ instance_id ] . pan , PANORAMA_MIN , PANORAMA_MAX , - 1.0 , 1.0 ) ) ;
eeprom_write ( ) ;
break ;
case 32 : // BankSelect LSB
# ifdef DEBUG
Serial . println ( F ( " BANK-SELECT CC " ) ) ;
# endif
configuration . dexed [ instance_id ] . bank = inValue ;
eeprom_write ( ) ;
break ;
case 64 :
MicroDexed [ instance_id ] - > setSustain ( inValue > 63 ) ;
if ( ! MicroDexed [ instance_id ] - > getSustain ( ) )
{
for ( uint8_t note = 0 ; note < MicroDexed [ instance_id ] - > getMaxNotes ( ) ; note + + )
{
if ( MicroDexed [ instance_id ] - > voices [ note ] . sustained & & ! MicroDexed [ instance_id ] - > voices [ note ] . keydown )
{
MicroDexed [ instance_id ] - > voices [ note ] . dx7_note - > keyup ( ) ;
MicroDexed [ instance_id ] - > voices [ note ] . sustained = false ;
}
}
}
break ;
case 65 :
MicroDexed [ instance_id ] - > setPortamentoMode ( configuration . dexed [ instance_id ] . portamento_mode , configuration . dexed [ instance_id ] . portamento_glissando , configuration . dexed [ instance_id ] . portamento_time ) ;
eeprom_write ( ) ;
break ;
# if defined(USE_FX)
case 103 : // CC 103: filter resonance
configuration . dexed [ instance_id ] . filter_resonance = map ( inValue , 0 , 0x7f , FILTER_RESONANCE_MIN , FILTER_RESONANCE_MAX ) ;
MicroDexed [ instance_id ] - > fx . Reso = mapfloat ( configuration . dexed [ instance_id ] . filter_resonance , FILTER_RESONANCE_MIN , FILTER_RESONANCE_MAX , 1.0 , 0.0 ) ;
eeprom_write ( ) ;
break ;
case 104 : // CC 104: filter cutoff
configuration . dexed [ instance_id ] . filter_cutoff = map ( inValue , 0 , 0x7f , FILTER_CUTOFF_MIN , FILTER_CUTOFF_MAX ) ;
MicroDexed [ instance_id ] - > fx . Cutoff = mapfloat ( configuration . dexed [ instance_id ] . filter_cutoff , FILTER_CUTOFF_MIN , FILTER_CUTOFF_MAX , 1.0 , 0.0 ) ;
eeprom_write ( ) ;
break ;
case 105 : // CC 105: delay time
configuration . delay_time = map ( inValue , 0 , 0x7f , DELAY_TIME_MIN , DELAY_TIME_MAX ) ;
delay_r . delay ( 0 , configuration . delay_time * 10 ) ;
delay_l . delay ( 0 , configuration . delay_time * 10 ) ;
eeprom_write ( ) ;
case 106 : // CC 106: delay feedback
configuration . delay_feedback = map ( inValue , 0 , 0x7f , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX ) ;
//delay_fb_mixer_r.gain(0, 1.0); // original signal
delay_fb_mixer_r . gain ( 1 , mapfloat ( configuration . delay_feedback , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX , 0.0 , 1.0 ) ) ; // amount of feedback
//delay_fb_mixer_l.gain(0, 1.0); // original signal
delay_fb_mixer_l . gain ( 1 , mapfloat ( configuration . delay_feedback , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX , 0.0 , 1.0 ) ) ; // amount of feedback
eeprom_write ( ) ;
break ;
case 107 : // CC 107: delay volume
configuration . dexed [ instance_id ] . delay_send = map ( inValue , 0 , 0x7f , DELAY_SEND_MIN , DELAY_SEND_MAX ) ;
master_mixer_r . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
eeprom_write ( ) ;
break ;
# endif
case 120 :
MicroDexed [ instance_id ] - > panic ( ) ;
break ;
case 121 :
MicroDexed [ instance_id ] - > resetControllers ( ) ;
break ;
case 123 :
MicroDexed [ instance_id ] - > notesOff ( ) ;
break ;
case 126 :
MicroDexed [ instance_id ] - > setMonoMode ( true ) ;
eeprom_write ( ) ;
break ;
case 127 :
MicroDexed [ instance_id ] - > setMonoMode ( false ) ;
eeprom_write ( ) ;
break ;
}
}
}
}
void handleAfterTouch ( byte inChannel , byte inPressure )
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( checkMidiChannel ( inChannel , instance_id ) )
{
MicroDexed [ instance_id ] - > controllers . aftertouch_cc = inPressure ;
MicroDexed [ instance_id ] - > controllers . refresh ( ) ;
}
}
}
void handlePitchBend ( byte inChannel , int inPitch )
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( checkMidiChannel ( inChannel , instance_id ) )
{
MicroDexed [ instance_id ] - > controllers . values_ [ kControllerPitch ] = inPitch + 0x2000 ; // -8192 to +8191 --> 0 to 16383
}
}
}
void handleProgramChange ( byte inChannel , byte inProgram )
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( checkMidiChannel ( inChannel , instance_id ) )
{
if ( inProgram < MAX_VOICES - 1 )
{
# ifdef DISPLAY_LCD_SPI
change_disp_sd ( false ) ;
# endif
load_sysex ( configuration . dexed [ instance_id ] . bank , inProgram , instance_id ) ;
# ifdef DISPLAY_LCD_SPI
change_disp_sd ( true ) ;
# endif
}
}
}
}
void handleSystemExclusive ( byte * sysex , uint len )
{
/*
SYSEX MESSAGE : Parameter Change
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bits hex description
11110000 F0 Status byte - start sysex
0 iiiiiii 43 ID # ( i = 67 ; Yamaha )
0 sssnnnn 10 Sub - status ( s = 1 ) & channel number ( n = 0 ; ch 1 )
0 gggggpp * * parameter group # ( g = 0 ; voice , g = 2 ; function )
0 ppppppp * * parameter # ( these are listed in next section )
Note that voice parameter # ' s can go over 128 so
the pp bits in the group byte are either 00 for
par # 0 - 127 or 01 for par # 128 - 155. In the latter case
you add 128 to the 0 ppppppp byte to compute par # .
0 ddddddd * * data byte
11110111 F7 Status - end sysex
*/
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( ! checkMidiChannel ( ( sysex [ 2 ] & 0x0f ) + 1 , instance_id ) )
{
# ifdef DEBUG
Serial . print ( F ( " INSTANCE " ) ) ;
Serial . print ( instance_id , DEC ) ;
Serial . println ( F ( " : SYSEX-MIDI-Channel mismatch " ) ) ;
# endif
return ;
}
# ifdef DEBUG
Serial . print ( F ( " INSTANCE " ) ) ;
Serial . print ( instance_id , DEC ) ;
Serial . print ( F ( " : SYSEX-Data[ " ) ) ;
Serial . print ( len , DEC ) ;
Serial . print ( F ( " ] " ) ) ;
for ( uint8_t i = 0 ; i < len ; i + + )
{
Serial . print ( F ( " " ) ) ;
Serial . print ( sysex [ i ] , DEC ) ;
}
Serial . println ( ) ;
# endif
if ( sysex [ 1 ] ! = 0x43 ) // check for Yamaha sysex
{
# ifdef DEBUG
Serial . println ( F ( " E: SysEx vendor not Yamaha. " ) ) ;
# endif
return ;
}
# ifdef DEBUG
Serial . print ( F ( " Substatus: [ " ) ) ;
Serial . print ( ( sysex [ 2 ] & 0x70 ) > > 4 ) ;
Serial . println ( F ( " ] " ) ) ;
# endif
// parse parameter change
if ( len = = 7 )
{
if ( ( ( sysex [ 3 ] & 0x7c ) > > 2 ) ! = 0 & & ( ( sysex [ 3 ] & 0x7c ) > > 2 ) ! = 2 )
{
# ifdef DEBUG
Serial . println ( F ( " E: Not a SysEx parameter or function parameter change. " ) ) ;
# endif
return ;
}
if ( sysex [ 6 ] ! = 0xf7 )
{
# ifdef DEBUG
Serial . println ( F ( " E: SysEx end status byte not detected. " ) ) ;
# endif
return ;
}
sysex [ 4 ] & = 0x7f ;
sysex [ 5 ] & = 0x7f ;
if ( ( ( sysex [ 3 ] & 0x7c ) > > 2 ) = = 0 )
{
MicroDexed [ instance_id ] - > notesOff ( ) ;
for ( uint8_t i = 0 ; i < 128 | | sysex [ 5 ] ! = 0xf7 ; i + + )
MicroDexed [ instance_id ] - > data [ sysex [ 4 ] + ( ( sysex [ 3 ] & 0x03 ) * 128 ) + i ] = sysex [ 5 ] ; // set parameter
MicroDexed [ instance_id ] - > doRefreshVoice ( ) ;
}
else
{
switch ( sysex [ 4 ] )
{
case 65 :
configuration . dexed [ instance_id ] . pb_range = constrain ( sysex [ 4 ] , PB_RANGE_MIN , PB_RANGE_MAX ) ;
MicroDexed [ instance_id ] - > controllers . values_ [ kControllerPitchRange ] = configuration . dexed [ instance_id ] . pb_range ;
break ;
case 66 :
configuration . dexed [ instance_id ] . pb_step = constrain ( sysex [ 4 ] , PB_STEP_MIN , PB_STEP_MAX ) ;
MicroDexed [ instance_id ] - > controllers . values_ [ kControllerPitchStep ] = configuration . dexed [ instance_id ] . pb_step ;
break ;
case 67 :
configuration . dexed [ instance_id ] . portamento_mode = constrain ( sysex [ 4 ] , PORTAMENTO_MODE_MIN , PORTAMENTO_MODE_MAX ) ;
MicroDexed [ instance_id ] - > setPortamentoMode ( configuration . dexed [ instance_id ] . portamento_mode , configuration . dexed [ instance_id ] . portamento_glissando , configuration . dexed [ instance_id ] . portamento_time ) ;
break ;
case 68 :
configuration . dexed [ instance_id ] . portamento_glissando = constrain ( sysex [ 4 ] , PORTAMENTO_GLISSANDO_MIN , PORTAMENTO_GLISSANDO_MAX ) ;
MicroDexed [ instance_id ] - > setPortamentoMode ( configuration . dexed [ instance_id ] . portamento_mode , configuration . dexed [ instance_id ] . portamento_glissando , configuration . dexed [ instance_id ] . portamento_time ) ;
break ;
case 69 :
configuration . dexed [ instance_id ] . portamento_time = constrain ( sysex [ 4 ] , PORTAMENTO_TIME_MIN , PORTAMENTO_TIME_MAX ) ;
MicroDexed [ instance_id ] - > setPortamentoMode ( configuration . dexed [ instance_id ] . portamento_mode , configuration . dexed [ instance_id ] . portamento_glissando , configuration . dexed [ instance_id ] . portamento_time ) ;
break ;
case 70 :
configuration . dexed [ instance_id ] . mw_range = constrain ( sysex [ 4 ] , MW_RANGE_MIN , MW_RANGE_MAX ) ;
MicroDexed [ instance_id ] - > controllers . wheel . setRange ( configuration . dexed [ instance_id ] . mw_range ) ;
break ;
case 71 :
configuration . dexed [ instance_id ] . mw_assign = constrain ( sysex [ 4 ] , MW_ASSIGN_MIN , MW_ASSIGN_MAX ) ;
MicroDexed [ instance_id ] - > controllers . wheel . setTarget ( configuration . dexed [ instance_id ] . mw_assign ) ;
break ;
case 72 :
configuration . dexed [ instance_id ] . fc_range = constrain ( sysex [ 4 ] , FC_RANGE_MIN , FC_RANGE_MAX ) ;
MicroDexed [ instance_id ] - > controllers . foot . setRange ( configuration . dexed [ instance_id ] . fc_range ) ;
break ;
case 73 :
configuration . dexed [ instance_id ] . fc_assign = constrain ( sysex [ 4 ] , FC_ASSIGN_MIN , FC_ASSIGN_MAX ) ;
MicroDexed [ instance_id ] - > controllers . foot . setTarget ( configuration . dexed [ instance_id ] . fc_assign ) ;
break ;
case 74 :
configuration . dexed [ instance_id ] . bc_range = constrain ( sysex [ 4 ] , BC_RANGE_MIN , BC_RANGE_MAX ) ;
MicroDexed [ instance_id ] - > controllers . breath . setRange ( configuration . dexed [ instance_id ] . bc_range ) ;
break ;
case 75 :
configuration . dexed [ instance_id ] . bc_assign = constrain ( sysex [ 4 ] , BC_ASSIGN_MIN , BC_ASSIGN_MAX ) ;
MicroDexed [ instance_id ] - > controllers . breath . setTarget ( configuration . dexed [ instance_id ] . bc_assign ) ;
break ;
case 76 :
configuration . dexed [ instance_id ] . at_range = constrain ( sysex [ 4 ] , AT_RANGE_MIN , AT_RANGE_MAX ) ;
MicroDexed [ instance_id ] - > controllers . at . setRange ( configuration . dexed [ instance_id ] . at_range ) ;
break ;
case 77 :
configuration . dexed [ instance_id ] . at_assign = constrain ( sysex [ 4 ] , AT_ASSIGN_MIN , AT_ASSIGN_MAX ) ;
MicroDexed [ instance_id ] - > controllers . at . setTarget ( configuration . dexed [ instance_id ] . at_assign ) ;
break ;
default :
MicroDexed [ instance_id ] - > data [ sysex [ 4 ] ] = sysex [ 5 ] ; // set function parameter
break ;
}
MicroDexed [ instance_id ] - > controllers . refresh ( ) ;
}
# ifdef DEBUG
Serial . print ( F ( " SysEx " ) ) ;
if ( ( ( sysex [ 3 ] & 0x7c ) > > 2 ) = = 0 )
{
Serial . println ( F ( " voice: " ) ) ;
show_patch ( instance_id ) ;
}
else
{
Serial . print ( F ( " function: " ) ) ;
Serial . print ( sysex [ 4 ] , DEC ) ;
Serial . print ( F ( " = " ) ) ;
Serial . println ( sysex [ 5 ] , DEC ) ;
}
# endif
}
else if ( len = = 163 )
{
int32_t bulk_checksum_calc = 0 ;
int8_t bulk_checksum = sysex [ 161 ] ;
// 1 Voice bulk upload
# ifdef DEBUG
Serial . println ( F ( " One Voice bulk upload " ) ) ;
# endif
if ( sysex [ 162 ] ! = 0xf7 )
{
# ifdef DEBUG
Serial . println ( F ( " E: Found no SysEx end marker. " ) ) ;
# endif
return ;
}
if ( ( sysex [ 3 ] & 0x7f ) ! = 0 )
{
# ifdef DEBUG
Serial . println ( F ( " E: Not a SysEx voice bulk upload. " ) ) ;
# endif
return ;
}
if ( ( ( sysex [ 4 ] < < 7 ) | sysex [ 5 ] ) ! = 0x9b )
{
# ifdef DEBUG
Serial . println ( F ( " E: Wrong length for SysEx voice bulk upload (not 155). " ) ) ;
# endif
return ;
}
// checksum calculation
for ( uint8_t i = 0 ; i < 155 ; i + + )
{
bulk_checksum_calc - = sysex [ i + 6 ] ;
}
bulk_checksum_calc & = 0x7f ;
if ( bulk_checksum_calc ! = bulk_checksum )
{
# ifdef DEBUG
Serial . print ( F ( " E: Checksum error for one voice [0x " ) ) ;
Serial . print ( bulk_checksum , HEX ) ;
Serial . print ( F ( " /0x " ) ) ;
Serial . print ( bulk_checksum_calc , HEX ) ;
Serial . println ( F ( " ] " ) ) ;
# endif
return ;
}
// load sysex-data into voice memory
MicroDexed [ instance_id ] - > loadVoiceParameters ( & sysex [ 6 ] ) ;
//MicroDexed[instance_id]->initGlobalParameters();
// manipulate UI names and numbers
strncpy ( voice_name [ instance_id ] , ( char * ) & sysex [ 151 ] , sizeof ( voice_name [ instance_id ] ) - 1 ) ;
Serial . print ( F ( " Got voice [ " ) ) ;
Serial . print ( voice_name [ instance_id ] ) ;
Serial . println ( F ( " ]. " ) ) ;
}
# ifdef DEBUG
else
Serial . println ( F ( " E: SysEx parameter length wrong. " ) ) ;
# endif
}
}
void handleTimeCodeQuarterFrame ( byte data )
{
;
}
void handleAfterTouchPoly ( byte inChannel , byte inNumber , byte inVelocity )
{
;
}
void handleSongSelect ( byte inSong )
{
;
}
void handleTuneRequest ( void )
{
;
}
void handleClock ( void )
{
midi_timing_counter + + ;
if ( midi_timing_counter % 24 = = 0 )
{
midi_timing_quarter = midi_timing_timestep ;
midi_timing_counter = 0 ;
midi_timing_timestep = 0 ;
// Adjust delay control here
# ifdef DEBUG
Serial . print ( F ( " MIDI Clock: " ) ) ;
Serial . print ( 60000 / midi_timing_quarter , DEC ) ;
Serial . print ( F ( " bpm ( " ) ) ;
Serial . print ( midi_timing_quarter , DEC ) ;
Serial . println ( F ( " ms per quarter) " ) ) ;
# endif
}
}
void handleStart ( void )
{
;
}
void handleContinue ( void )
{
;
}
void handleStop ( void )
{
;
}
void handleActiveSensing ( void )
{
;
}
void handleSystemReset ( void )
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
# ifdef DEBUG
Serial . println ( F ( " MIDI SYSEX RESET " ) ) ;
# endif
MicroDexed [ instance_id ] - > notesOff ( ) ;
MicroDexed [ instance_id ] - > panic ( ) ;
MicroDexed [ instance_id ] - > resetControllers ( ) ;
}
}
/******************************************************************************
MIDI HELPER
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool checkMidiChannel ( byte inChannel , uint8_t instance_id )
{
// check for MIDI channel
if ( configuration . dexed [ instance_id ] . midi_channel = = MIDI_CHANNEL_OMNI )
{
return ( true ) ;
}
else if ( inChannel ! = configuration . dexed [ instance_id ] . midi_channel )
{
# ifdef DEBUG
Serial . print ( F ( " INSTANCE " ) ) ;
Serial . print ( instance_id , DEC ) ;
Serial . print ( F ( " : Ignoring MIDI data on channel " ) ) ;
Serial . print ( inChannel ) ;
Serial . print ( F ( " (listening on " ) ) ;
Serial . print ( configuration . dexed [ instance_id ] . midi_channel ) ;
Serial . println ( F ( " ) " ) ) ;
# endif
return ( false ) ;
}
return ( true ) ;
}
/******************************************************************************
VOLUME HELPER
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void set_volume ( uint8_t v , uint8_t m )
{
configuration . vol = v ;
if ( configuration . vol > 100 )
configuration . vol = 100 ;
configuration . mono = m ;
# ifdef DEBUG
Serial . print ( F ( " Setting volume: VOL= " ) ) ;
Serial . println ( v , DEC ) ;
# endif
volume_r . gain ( v / 100.0 ) ;
volume_l . gain ( v / 100.0 ) ;
switch ( m )
{
case 0 : // stereo
stereo2mono . stereo ( true ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
mono2stereo [ instance_id ] - > panorama ( mapfloat ( configuration . dexed [ instance_id ] . pan , PANORAMA_MIN , PANORAMA_MAX , - 1.0 , 1.0 ) ) ;
modchorus_inverter . gain ( - 1.0 ) ; // stereo mode
break ;
case 1 : // mono both
stereo2mono . stereo ( false ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
mono2stereo [ instance_id ] - > panorama ( mapfloat ( PANORAMA_DEFAULT , PANORAMA_MIN , PANORAMA_MAX , - 1.0 , 1.0 ) ) ;
modchorus_inverter . gain ( 1.0 ) ;
break ;
case 2 : // mono right
volume_l . gain ( 0.0 ) ;
stereo2mono . stereo ( false ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
mono2stereo [ instance_id ] - > panorama ( mapfloat ( PANORAMA_MAX , PANORAMA_MIN , PANORAMA_MAX , - 1.0 , 1.0 ) ) ;
modchorus_inverter . gain ( 1.0 ) ;
break ;
case 3 : // mono left
volume_r . gain ( 0.0 ) ;
stereo2mono . stereo ( false ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
mono2stereo [ instance_id ] - > panorama ( mapfloat ( PANORAMA_MIN , PANORAMA_MIN , PANORAMA_MAX , - 1.0 , 1.0 ) ) ;
modchorus_inverter . gain ( 1.0 ) ;
break ;
}
}
/******************************************************************************
EEPROM HELPER
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void initial_values_from_eeprom ( bool init )
{
uint32_t checksum ;
config_t tmp_conf ;
if ( init = = true )
init_configuration ( ) ;
else
{
# ifdef DEBUG
Serial . println ( F ( " Loading inital data from EEPROM. " ) ) ;
# endif
EEPROM . get ( EEPROM_START_ADDRESS , tmp_conf ) ;
checksum = crc32 ( ( byte * ) & tmp_conf + 4 , sizeof ( tmp_conf ) - 4 ) ;
# ifdef DEBUG
Serial . print ( F ( " EEPROM checksum: 0x " ) ) ;
Serial . print ( tmp_conf . checksum , HEX ) ;
Serial . print ( F ( " / 0x " ) ) ;
Serial . println ( checksum , HEX ) ;
# endif
if ( checksum ! = tmp_conf . checksum )
{
# ifdef DEBUG
Serial . println ( F ( " Checksum mismatch -> initializing EEPROM! " ) ) ;
# endif
init_configuration ( ) ;
}
else
{
EEPROM . get ( EEPROM_START_ADDRESS , configuration ) ;
check_configuration ( ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
MicroDexed [ instance_id ] - > setPBController ( configuration . dexed [ instance_id ] . pb_range , configuration . dexed [ instance_id ] . pb_step ) ;
MicroDexed [ instance_id ] - > setMWController ( configuration . dexed [ instance_id ] . mw_range , configuration . dexed [ instance_id ] . mw_assign , configuration . dexed [ instance_id ] . mw_mode ) ;
MicroDexed [ instance_id ] - > setFCController ( configuration . dexed [ instance_id ] . fc_range , configuration . dexed [ instance_id ] . fc_assign , configuration . dexed [ instance_id ] . fc_mode ) ;
MicroDexed [ instance_id ] - > setBCController ( configuration . dexed [ instance_id ] . bc_range , configuration . dexed [ instance_id ] . bc_assign , configuration . dexed [ instance_id ] . bc_mode ) ;
MicroDexed [ instance_id ] - > setATController ( configuration . dexed [ instance_id ] . at_range , configuration . dexed [ instance_id ] . at_assign , configuration . dexed [ instance_id ] . at_mode ) ;
MicroDexed [ instance_id ] - > setOPs ( configuration . dexed [ instance_id ] . op_enabled ) ;
MicroDexed [ instance_id ] - > doRefreshVoice ( ) ;
# if defined(USE_FX)
chorus_send_mixer_r . gain ( instance_id , configuration . dexed [ instance_id ] . chorus_send / 100.0 ) ;
chorus_send_mixer_r . gain ( instance_id , configuration . dexed [ instance_id ] . chorus_send / 100.0 ) ;
delay_send_mixer_l . gain ( instance_id , configuration . dexed [ instance_id ] . delay_send / 100.0 ) ;
delay_send_mixer_l . gain ( instance_id , configuration . dexed [ instance_id ] . delay_send / 100.0 ) ;
delay_fb_mixer_r . gain ( 0 , 1.0 ) ; // original signal
delay_fb_mixer_r . gain ( 1 , mapfloat ( configuration . delay_feedback , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX , 0.0 , 1.0 ) ) ; // amount of feedback
delay_fb_mixer_l . gain ( 0 , 1.0 ) ; // original signal
delay_fb_mixer_l . gain ( 1 , mapfloat ( configuration . delay_feedback , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX , 0.0 , 1.0 ) ) ; // amount of feedback
reverb_send_mixer_r . gain ( instance_id , configuration . dexed [ instance_id ] . reverb_send / 100.0 ) ;
reverb_send_mixer_l . gain ( instance_id , configuration . dexed [ instance_id ] . reverb_send / 100.0 ) ;
// MicroDexed[instance_id]->fx.Gain = configuration.dexed[instance_id].sound_intensity / 100.0;
MicroDexed [ instance_id ] - > fx . Gain = 1.0 ;
MicroDexed [ instance_id ] - > fx . Reso = mapfloat ( configuration . dexed [ instance_id ] . filter_resonance , FILTER_RESONANCE_MIN , FILTER_RESONANCE_MAX , 1.0 , 0.0 ) ;
MicroDexed [ instance_id ] - > fx . Cutoff = mapfloat ( configuration . dexed [ instance_id ] . filter_cutoff , FILTER_CUTOFF_MIN , FILTER_CUTOFF_MAX , 1.0 , 0.0 ) ;
# endif
MicroDexed [ instance_id ] - > setOPs ( configuration . dexed [ instance_id ] . op_enabled ) ;
dexed_level [ instance_id ] - > gain ( mapfloat ( configuration . dexed [ instance_id ] . sound_intensity , SOUND_INTENSITY_MIN , SOUND_INTENSITY_MAX , 0.0 , SOUND_INTENSITY_AMP_MAX ) ) ;
}
}
# ifdef DEBUG
Serial . println ( F ( " OK, loaded! " ) ) ;
# endif
master_mixer_r . gain ( DEXED , 1.0 ) ;
master_mixer_l . gain ( DEXED , 1.0 ) ;
master_mixer_r . gain ( CHORUS , mapfloat ( configuration . chorus_level , CHORUS_LEVEL_MIN , CHORUS_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( CHORUS , mapfloat ( configuration . chorus_level , CHORUS_LEVEL_MIN , CHORUS_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_r . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_r . gain ( REVERB , mapfloat ( configuration . reverb_level , REVERB_LEVEL_MIN , REVERB_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( REVERB , mapfloat ( configuration . reverb_level , REVERB_LEVEL_MIN , REVERB_LEVEL_MAX , 0.0 , 1.0 ) ) ;
set_volume ( configuration . vol , configuration . mono ) ;
}
# ifdef DEBUG
show_configuration ( ) ;
# endif
}
void check_configuration ( void )
{
configuration . instances = constrain ( configuration . instances , INSTANCES_MIN , INSTANCES_MAX ) ;
configuration . vol = constrain ( configuration . vol , VOLUME_MIN , VOLUME_MAX ) ;
configuration . mono = constrain ( configuration . mono , MONO_MIN , MONO_MAX ) ;
configuration . reverb_roomsize = constrain ( configuration . reverb_roomsize , REVERB_ROOMSIZE_MIN , REVERB_ROOMSIZE_MAX ) ;
configuration . reverb_damping = constrain ( configuration . reverb_damping , REVERB_DAMPING_MIN , REVERB_DAMPING_MAX ) ;
configuration . reverb_level = constrain ( configuration . reverb_level , REVERB_LEVEL_MIN , REVERB_LEVEL_MAX ) ;
configuration . chorus_frequency = constrain ( configuration . chorus_frequency , CHORUS_FREQUENCY_MIN , CHORUS_FREQUENCY_MAX ) ;
configuration . chorus_waveform = constrain ( configuration . chorus_waveform , CHORUS_WAVEFORM_MIN , CHORUS_WAVEFORM_MAX ) ;
configuration . chorus_depth = constrain ( configuration . chorus_depth , CHORUS_DEPTH_MIN , CHORUS_DEPTH_MAX ) ;
configuration . chorus_level = constrain ( configuration . chorus_level , CHORUS_LEVEL_MIN , CHORUS_LEVEL_MAX ) ;
configuration . delay_time = constrain ( configuration . delay_time , DELAY_TIME_MIN / 10 , DELAY_TIME_MAX / 10 ) ;
configuration . delay_feedback = constrain ( configuration . delay_feedback , DELAY_FEEDBACK_MIN , DELAY_FEEDBACK_MAX ) ;
configuration . delay_level = constrain ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX ) ;
configuration . soft_midi_thru = constrain ( configuration . soft_midi_thru , SOFT_MIDI_THRU_MIN , SOFT_MIDI_THRU_MAX ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
configuration . dexed [ instance_id ] . midi_channel = constrain ( configuration . dexed [ instance_id ] . midi_channel , MIDI_CHANNEL_MIN , MIDI_CHANNEL_MAX ) ;
configuration . dexed [ instance_id ] . bank = constrain ( configuration . dexed [ instance_id ] . bank , 0 , MAX_BANKS - 1 ) ;
configuration . dexed [ instance_id ] . voice = constrain ( configuration . dexed [ instance_id ] . voice , 0 , MAX_VOICES - 1 ) ;
configuration . dexed [ instance_id ] . lowest_note = constrain ( configuration . dexed [ instance_id ] . lowest_note , INSTANCE_LOWEST_NOTE_MIN , INSTANCE_LOWEST_NOTE_MAX ) ;
configuration . dexed [ instance_id ] . highest_note = constrain ( configuration . dexed [ instance_id ] . highest_note , INSTANCE_HIGHEST_NOTE_MIN , INSTANCE_HIGHEST_NOTE_MAX ) ;
configuration . dexed [ instance_id ] . reverb_send = constrain ( configuration . dexed [ instance_id ] . reverb_send , REVERB_SEND_MIN , REVERB_SEND_MAX ) ;
configuration . dexed [ instance_id ] . chorus_send = constrain ( configuration . dexed [ instance_id ] . chorus_send , CHORUS_SEND_MIN , CHORUS_SEND_MAX ) ;
configuration . dexed [ instance_id ] . delay_send = constrain ( configuration . dexed [ instance_id ] . delay_send , DELAY_SEND_MIN , DELAY_SEND_MAX ) ;
configuration . dexed [ instance_id ] . filter_cutoff = constrain ( configuration . dexed [ instance_id ] . filter_cutoff , FILTER_CUTOFF_MIN , FILTER_CUTOFF_MAX ) ;
configuration . dexed [ instance_id ] . filter_resonance = constrain ( configuration . dexed [ instance_id ] . filter_resonance , FILTER_RESONANCE_MIN , FILTER_RESONANCE_MAX ) ;
configuration . dexed [ instance_id ] . sound_intensity = constrain ( configuration . dexed [ instance_id ] . sound_intensity , SOUND_INTENSITY_MIN , SOUND_INTENSITY_MAX ) ;
configuration . dexed [ instance_id ] . pan = constrain ( configuration . dexed [ instance_id ] . pan , PANORAMA_MIN , PANORAMA_MAX ) ;
configuration . dexed [ instance_id ] . transpose = constrain ( configuration . dexed [ instance_id ] . transpose , TRANSPOSE_MIN , TRANSPOSE_MAX ) ;
configuration . dexed [ instance_id ] . tune = constrain ( configuration . dexed [ instance_id ] . tune , TUNE_MIN , TUNE_MAX ) ;
configuration . dexed [ instance_id ] . polyphony = constrain ( configuration . dexed [ instance_id ] . polyphony , POLYPHONY_MIN , POLYPHONY_MAX ) ;
configuration . dexed [ instance_id ] . velocity_level = constrain ( configuration . dexed [ instance_id ] . velocity_level , VELOCITY_LEVEL_MIN , VELOCITY_LEVEL_MAX ) ;
configuration . dexed [ instance_id ] . engine = constrain ( configuration . dexed [ instance_id ] . engine , ENGINE_MIN , ENGINE_MAX ) ;
configuration . dexed [ instance_id ] . monopoly = constrain ( configuration . dexed [ instance_id ] . monopoly , MONOPOLY_MIN , MONOPOLY_MAX ) ;
configuration . dexed [ instance_id ] . note_refresh = constrain ( configuration . dexed [ instance_id ] . note_refresh , NOTE_REFRESH_MIN , NOTE_REFRESH_MAX ) ;
configuration . dexed [ instance_id ] . pb_range = constrain ( configuration . dexed [ instance_id ] . pb_range , PB_RANGE_MIN , PB_RANGE_MAX ) ;
configuration . dexed [ instance_id ] . pb_step = constrain ( configuration . dexed [ instance_id ] . pb_step , PB_STEP_MIN , PB_STEP_MAX ) ;
configuration . dexed [ instance_id ] . mw_range = constrain ( configuration . dexed [ instance_id ] . mw_range , MW_RANGE_MIN , MW_RANGE_MAX ) ;
configuration . dexed [ instance_id ] . mw_assign = constrain ( configuration . dexed [ instance_id ] . mw_assign , MW_ASSIGN_MIN , MW_ASSIGN_MAX ) ;
configuration . dexed [ instance_id ] . mw_mode = constrain ( configuration . dexed [ instance_id ] . mw_mode , MW_MODE_MIN , MW_MODE_MAX ) ;
configuration . dexed [ instance_id ] . fc_range = constrain ( configuration . dexed [ instance_id ] . fc_range , FC_RANGE_MIN , FC_RANGE_MAX ) ;
configuration . dexed [ instance_id ] . fc_assign = constrain ( configuration . dexed [ instance_id ] . fc_assign , FC_ASSIGN_MIN , FC_ASSIGN_MAX ) ;
configuration . dexed [ instance_id ] . fc_mode = constrain ( configuration . dexed [ instance_id ] . fc_mode , FC_MODE_MIN , FC_MODE_MAX ) ;
configuration . dexed [ instance_id ] . bc_range = constrain ( configuration . dexed [ instance_id ] . bc_range , BC_RANGE_MIN , BC_RANGE_MAX ) ;
configuration . dexed [ instance_id ] . bc_assign = constrain ( configuration . dexed [ instance_id ] . bc_assign , BC_ASSIGN_MIN , BC_ASSIGN_MAX ) ;
configuration . dexed [ instance_id ] . bc_mode = constrain ( configuration . dexed [ instance_id ] . bc_mode , BC_MODE_MIN , BC_MODE_MAX ) ;
configuration . dexed [ instance_id ] . at_range = constrain ( configuration . dexed [ instance_id ] . at_range , AT_RANGE_MIN , AT_RANGE_MAX ) ;
configuration . dexed [ instance_id ] . at_assign = constrain ( configuration . dexed [ instance_id ] . at_assign , AT_ASSIGN_MIN , AT_ASSIGN_MAX ) ;
configuration . dexed [ instance_id ] . at_mode = constrain ( configuration . dexed [ instance_id ] . at_mode , AT_MODE_MIN , AT_MODE_MAX ) ;
configuration . dexed [ instance_id ] . portamento_mode = constrain ( configuration . dexed [ instance_id ] . portamento_mode , PORTAMENTO_MODE_MIN , PORTAMENTO_MODE_MAX ) ;
configuration . dexed [ instance_id ] . portamento_glissando = constrain ( configuration . dexed [ instance_id ] . portamento_glissando , PORTAMENTO_GLISSANDO_MIN , PORTAMENTO_GLISSANDO_MAX ) ;
configuration . dexed [ instance_id ] . portamento_time = constrain ( configuration . dexed [ instance_id ] . portamento_time , PORTAMENTO_TIME_MIN , PORTAMENTO_TIME_MAX ) ;
configuration . dexed [ instance_id ] . op_enabled = constrain ( configuration . dexed [ instance_id ] . op_enabled , OP_ENABLED_MIN , OP_ENABLED_MAX ) ;
}
master_mixer_r . gain ( CHORUS , mapfloat ( configuration . delay_level , CHORUS_LEVEL_MIN , CHORUS_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( CHORUS , mapfloat ( configuration . delay_level , CHORUS_LEVEL_MIN , CHORUS_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_r . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( DELAY , mapfloat ( configuration . delay_level , DELAY_LEVEL_MIN , DELAY_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_r . gain ( REVERB , mapfloat ( configuration . delay_level , REVERB_LEVEL_MIN , REVERB_LEVEL_MAX , 0.0 , 1.0 ) ) ;
master_mixer_l . gain ( REVERB , mapfloat ( configuration . delay_level , REVERB_LEVEL_MIN , REVERB_LEVEL_MAX , 0.0 , 1.0 ) ) ;
}
void init_configuration ( void )
{
# ifdef DEBUG
Serial . println ( F ( " INITIALIZING CONFIGURATION " ) ) ;
# endif
configuration . checksum = 0xffff ;
configuration . instances = INSTANCES_DEFAULT ;
configuration . vol = VOLUME_DEFAULT ;
configuration . mono = MONO_DEFAULT ;
configuration . reverb_roomsize = REVERB_ROOMSIZE_DEFAULT ;
configuration . reverb_damping = REVERB_DAMPING_DEFAULT ;
configuration . reverb_level = REVERB_LEVEL_DEFAULT ;
configuration . chorus_frequency = CHORUS_FREQUENCY_DEFAULT ;
configuration . chorus_waveform = CHORUS_WAVEFORM_DEFAULT ;
configuration . chorus_depth = CHORUS_DEPTH_DEFAULT ;
configuration . chorus_level = CHORUS_LEVEL_DEFAULT ;
configuration . delay_time = DELAY_TIME_DEFAULT / 10 ;
configuration . delay_feedback = DELAY_FEEDBACK_DEFAULT ;
configuration . delay_level = DELAY_LEVEL_DEFAULT ;
configuration . soft_midi_thru = SOFT_MIDI_THRU_DEFAULT ;
strcpy ( configuration . config_name , " INITCONFIG " ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
configuration . dexed [ instance_id ] . midi_channel = DEFAULT_MIDI_CHANNEL ;
configuration . dexed [ instance_id ] . bank = SYSEXBANK_DEFAULT ;
configuration . dexed [ instance_id ] . voice = SYSEXSOUND_DEFAULT ;
configuration . dexed [ instance_id ] . lowest_note = INSTANCE_LOWEST_NOTE_MIN ;
configuration . dexed [ instance_id ] . highest_note = INSTANCE_HIGHEST_NOTE_MAX ;
configuration . dexed [ instance_id ] . reverb_send = REVERB_SEND_DEFAULT ;
configuration . dexed [ instance_id ] . chorus_send = CHORUS_SEND_DEFAULT ;
configuration . dexed [ instance_id ] . delay_send = DELAY_SEND_DEFAULT ;
configuration . dexed [ instance_id ] . filter_cutoff = FILTER_CUTOFF_DEFAULT ;
configuration . dexed [ instance_id ] . filter_resonance = FILTER_RESONANCE_DEFAULT ;
configuration . dexed [ instance_id ] . sound_intensity = SOUND_INTENSITY_DEFAULT ;
configuration . dexed [ instance_id ] . pan = PANORAMA_DEFAULT ;
configuration . dexed [ instance_id ] . transpose = TRANSPOSE_DEFAULT ;
configuration . dexed [ instance_id ] . tune = TUNE_DEFAULT ;
configuration . dexed [ instance_id ] . polyphony = POLYPHONY_DEFAULT ;
configuration . dexed [ instance_id ] . velocity_level = VELOCITY_LEVEL_DEFAULT ;
configuration . dexed [ instance_id ] . engine = ENGINE_DEFAULT ;
configuration . dexed [ instance_id ] . monopoly = MONOPOLY_DEFAULT ;
configuration . dexed [ instance_id ] . note_refresh = NOTE_REFRESH_DEFAULT ;
configuration . dexed [ instance_id ] . pb_range = PB_RANGE_DEFAULT ;
configuration . dexed [ instance_id ] . pb_step = PB_STEP_DEFAULT ;
configuration . dexed [ instance_id ] . mw_range = MW_RANGE_DEFAULT ;
configuration . dexed [ instance_id ] . mw_assign = MW_ASSIGN_DEFAULT ;
configuration . dexed [ instance_id ] . mw_mode = MW_MODE_DEFAULT ;
configuration . dexed [ instance_id ] . fc_range = FC_RANGE_DEFAULT ;
configuration . dexed [ instance_id ] . fc_assign = FC_ASSIGN_DEFAULT ;
configuration . dexed [ instance_id ] . fc_mode = FC_MODE_DEFAULT ;
configuration . dexed [ instance_id ] . bc_range = BC_RANGE_DEFAULT ;
configuration . dexed [ instance_id ] . bc_assign = BC_ASSIGN_DEFAULT ;
configuration . dexed [ instance_id ] . bc_mode = BC_MODE_DEFAULT ;
configuration . dexed [ instance_id ] . at_range = AT_RANGE_DEFAULT ;
configuration . dexed [ instance_id ] . at_assign = AT_ASSIGN_DEFAULT ;
configuration . dexed [ instance_id ] . at_mode = AT_MODE_DEFAULT ;
configuration . dexed [ instance_id ] . portamento_mode = PORTAMENTO_MODE_DEFAULT ;
configuration . dexed [ instance_id ] . portamento_glissando = PORTAMENTO_GLISSANDO_DEFAULT ;
configuration . dexed [ instance_id ] . portamento_time = PORTAMENTO_TIME_DEFAULT ;
configuration . dexed [ instance_id ] . op_enabled = OP_ENABLED_DEFAULT ;
MicroDexed [ instance_id ] - > controllers . refresh ( ) ;
}
set_volume ( configuration . vol , configuration . mono ) ;
eeprom_update ( ) ;
}
void eeprom_write ( void )
{
autostore = 0 ;
eeprom_update_flag = true ;
}
void eeprom_update ( void )
{
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
if ( active_voices [ instance_id ] > 0 )
autostore = 0 ;
else
{
eeprom_update_flag = false ;
configuration . checksum = crc32 ( ( byte * ) & configuration + 4 , sizeof ( configuration ) - 4 ) ;
EEPROM . put ( EEPROM_START_ADDRESS , configuration ) ;
# ifdef DEBUG
Serial . println ( F ( " Updating EEPROM " ) ) ;
show_configuration ( ) ;
# endif
}
}
}
/******************************************************************************
HELPERS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32_t crc32 ( byte * calc_start , uint16_t calc_bytes ) // base code from https://www.arduino.cc/en/Tutorial/EEPROMCrc
{
const uint32_t crc_table [ 16 ] =
{
0x00000000 , 0x1db71064 , 0x3b6e20c8 , 0x26d930ac ,
0x76dc4190 , 0x6b6b51f4 , 0x4db26158 , 0x5005713c ,
0xedb88320 , 0xf00f9344 , 0xd6d6a3e8 , 0xcb61b38c ,
0x9b64c2b0 , 0x86d3d2d4 , 0xa00ae278 , 0xbdbdf21c
} ;
uint32_t crc = ~ 0L ;
for ( byte * index = calc_start ; index < ( calc_start + calc_bytes ) ; + + index )
{
crc = crc_table [ ( crc ^ * index ) & 0x0f ] ^ ( crc > > 4 ) ;
crc = crc_table [ ( crc ^ ( * index > > 4 ) ) & 0x0f ] ^ ( crc > > 4 ) ;
crc = ~ crc ;
}
return ( crc ) ;
}
void generate_version_string ( char * buffer , uint8_t len )
{
char tmp [ 3 ] ;
memset ( buffer , 0 , len ) ;
strncat ( buffer , VERSION , len ) ;
# if defined(TEENSY3_5)
strncat ( buffer , " -3.5 " , 4 ) ;
# elif defined(TEENSY3_6)
strncat ( buffer , " -3.6 " , 4 ) ;
# elif defined(TEENSY4)
strncat ( buffer , " -4.0 " , 4 ) ;
# endif
# if defined(USE_FX)
strncat ( buffer , " FX " , 2 ) ;
# endif
# if defined(MAX_NOTES)
strncat ( buffer , " - " , 1 ) ;
itoa ( MAX_NOTES , tmp , 10 ) ;
strncat ( buffer , tmp , 2 ) ;
# endif
}
# ifdef DISPLAY_LCD_SPI
void change_disp_sd ( bool disp )
{
if ( sd_card > 0 )
{
digitalWrite ( sd_card , disp ) ;
digitalWrite ( U8X8_CS_PIN , ! disp ) ;
}
}
# endif
uint8_t check_sd_cards ( void )
{
uint8_t ret = 0 ;
memset ( sd_string , 0 , sizeof ( sd_string ) ) ;
for ( uint8_t i = 0 ; i < sizeof ( cs_pins ) ; i + + )
{
# ifdef DEBUG
Serial . print ( F ( " Checking CS pin " ) ) ;
Serial . print ( cs_pins [ i ] , DEC ) ;
Serial . println ( F ( " for SD card " ) ) ;
# endif
SPI . setMOSI ( mosi_pins [ i ] ) ;
SPI . setSCK ( sck_pins [ i ] ) ;
if ( SD . begin ( cs_pins [ i ] ) = = true )
{
# ifdef DEBUG
Serial . print ( F ( " Found. Using pin " ) ) ;
Serial . println ( cs_pins [ i ] , DEC ) ;
# endif
ret = cs_pins [ i ] ;
break ;
}
}
if ( ret > = 0 )
{
if ( ! card . init ( SPI_HALF_SPEED , ret ) )
{
# ifdef DEBUG
Serial . println ( F ( " SD card initialization failed. " ) ) ;
# endif
ret = - 1 ;
}
}
if ( ret > = 0 )
{
# ifdef DEBUG
Serial . print ( F ( " Card type: " ) ) ;
# endif
switch ( card . type ( ) ) {
case SD_CARD_TYPE_SD1 :
sprintf ( sd_string , " %-5s " , " SD1 " ) ;
# ifdef DEBUG
Serial . println ( F ( " SD1 " ) ) ;
# endif
break ;
case SD_CARD_TYPE_SD2 :
sprintf ( sd_string , " %-5s " , " SD2 " ) ;
# ifdef DEBUG
Serial . println ( F ( " SD2 " ) ) ;
# endif
break ;
case SD_CARD_TYPE_SDHC :
sprintf ( sd_string , " %-5s " , " SD2 " ) ;
# ifdef DEBUG
Serial . println ( F ( " SDHC " ) ) ;
# endif
break ;
default :
sprintf ( sd_string , " %-5s " , " UKNW " ) ;
# ifdef DEBUG
Serial . println ( F ( " Unknown " ) ) ;
# endif
}
if ( ! volume . init ( card ) )
{
# ifdef DEBUG
Serial . println ( F ( " Could not find FAT16/FAT32 partition. " ) ) ;
# endif
ret = - 1 ;
}
}
if ( ret > = 0 )
{
uint32_t volumesize ;
volumesize = volume . blocksPerCluster ( ) * volume . clusterCount ( ) / 2097152 ;
# ifdef DEBUG
Serial . print ( F ( " Volume type is FAT " ) ) ;
Serial . println ( volume . fatType ( ) , DEC ) ;
Serial . print ( F ( " Volume size (GB): " ) ) ;
Serial . println ( volumesize ) ;
# endif
sprintf ( sd_string + 5 , " FAT%2d %02dGB " , volume . fatType ( ) , int ( volumesize ) ) ;
}
# ifdef DEBUG
Serial . println ( sd_string ) ;
# endif
return ( ret ) ;
}
/******************************************************************************
DEBUG HELPER
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
void show_cpu_and_mem_usage ( void )
{
uint32_t sum_xrun = 0 ;
uint16_t sum_render_time_max = 0 ;
uint32_t sum_overload = 0 ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
sum_xrun + = MicroDexed [ instance_id ] - > xrun ;
sum_render_time_max + = MicroDexed [ instance_id ] - > render_time_max ;
sum_overload + = MicroDexed [ instance_id ] - > overload ;
MicroDexed [ instance_id ] - > render_time_max = 0 ;
}
if ( AudioProcessorUsageMax ( ) > 99.9 )
{
cpumax + + ;
# ifdef DEBUG
Serial . print ( F ( " * " ) ) ;
# endif
}
# ifdef DEBUG
else
Serial . print ( F ( " " ) ) ;
Serial . print ( F ( " CPU: " ) ) ;
Serial . print ( AudioProcessorUsage ( ) , 2 ) ;
Serial . print ( F ( " %|CPUMAX: " ) ) ;
Serial . print ( AudioProcessorUsageMax ( ) , 2 ) ;
Serial . print ( F ( " %|CPUMAXCNT: " ) ) ;
Serial . print ( cpumax , DEC ) ;
Serial . print ( F ( " |MEM: " ) ) ;
Serial . print ( AudioMemoryUsage ( ) , DEC ) ;
Serial . print ( F ( " |MEMMAX: " ) ) ;
Serial . print ( AudioMemoryUsageMax ( ) , DEC ) ;
Serial . print ( F ( " |RENDERTIMEMAX: " ) ) ;
Serial . print ( sum_render_time_max , DEC ) ;
Serial . print ( F ( " |XRUN: " ) ) ;
Serial . print ( sum_xrun , DEC ) ;
Serial . print ( F ( " |OVERLOAD: " ) ) ;
Serial . println ( sum_overload , DEC ) ;
Serial . print ( F ( " PEAKR: " ) ) ;
Serial . print ( peak_r , DEC ) ;
Serial . print ( F ( " |PEAKL: " ) ) ;
Serial . print ( peak_l , DEC ) ;
Serial . print ( F ( " |PEAKMD: " ) ) ;
Serial . print ( peak_dexed , DEC ) ;
Serial . print ( F ( " |ACTPEAKMD: " ) ) ;
Serial . print ( peak_dexed_value , 1 ) ;
Serial . print ( F ( " |BLOCKSIZE: " ) ) ;
Serial . println ( AUDIO_BLOCK_SAMPLES , DEC ) ;
Serial . print ( F ( " |ACTVOICES: " ) ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
Serial . print ( instance_id , DEC ) ;
Serial . print ( F ( " = " ) ) ;
Serial . print ( active_voices [ instance_id ] , DEC ) ;
if ( instance_id ! = NUM_DEXED - 1 )
Serial . print ( F ( " , " ) ) ;
}
Serial . println ( ) ;
# endif
AudioProcessorUsageMaxReset ( ) ;
AudioMemoryUsageMaxReset ( ) ;
}
# endif
# ifdef DEBUG
void show_configuration ( void )
{
Serial . println ( ) ;
Serial . println ( F ( " CONFIGURATION: " ) ) ;
Serial . print ( F ( " Checksum 0x " ) ) ; Serial . println ( configuration . checksum , HEX ) ;
Serial . print ( F ( " Instances " ) ) ; Serial . println ( configuration . instances , DEC ) ;
Serial . print ( F ( " Volume " ) ) ; Serial . println ( configuration . vol , DEC ) ;
Serial . print ( F ( " Mono " ) ) ; Serial . println ( configuration . mono , DEC ) ;
Serial . print ( F ( " Reverb Roomsize " ) ) ; Serial . println ( configuration . reverb_roomsize , DEC ) ;
Serial . print ( F ( " Reverb Damping " ) ) ; Serial . println ( configuration . reverb_damping , DEC ) ;
Serial . print ( F ( " Reverb Level " ) ) ; Serial . println ( configuration . reverb_level , DEC ) ;
Serial . print ( F ( " Chorus Frequency " ) ) ; Serial . println ( configuration . chorus_frequency , DEC ) ;
Serial . print ( F ( " Chorus Waveform " ) ) ; Serial . println ( configuration . chorus_waveform , DEC ) ;
Serial . print ( F ( " Chorus Depth " ) ) ; Serial . println ( configuration . chorus_depth , DEC ) ;
Serial . print ( F ( " Chorus Level " ) ) ; Serial . println ( configuration . chorus_level , DEC ) ;
Serial . print ( F ( " Delay Time " ) ) ; Serial . println ( configuration . delay_time , DEC ) ;
Serial . print ( F ( " Delay Feedback " ) ) ; Serial . println ( configuration . delay_feedback , DEC ) ;
Serial . print ( F ( " Delay Level " ) ) ; Serial . println ( configuration . delay_level , DEC ) ;
Serial . print ( F ( " Soft MIDI Thru " ) ) ; Serial . println ( configuration . soft_midi_thru , DEC ) ;
for ( uint8_t instance_id = 0 ; instance_id < NUM_DEXED ; instance_id + + )
{
Serial . print ( F ( " === DEXED INSTANCE " ) ) ;
Serial . print ( instance_id , DEC ) ;
Serial . println ( " === " ) ;
Serial . print ( F ( " MIDI-Channel " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . midi_channel , DEC ) ;
Serial . print ( F ( " Bank " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . bank , DEC ) ;
Serial . print ( F ( " Voice " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . voice , DEC ) ;
Serial . print ( F ( " Lowest Note " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . lowest_note , DEC ) ;
Serial . print ( F ( " Highest Note " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . highest_note , DEC ) ;
Serial . print ( F ( " Reverb Send " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . reverb_send , DEC ) ;
Serial . print ( F ( " Chorus Send " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . chorus_send , DEC ) ;
Serial . print ( F ( " Delay Send " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . delay_send , DEC ) ;
Serial . print ( F ( " Filter Cutoff " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . filter_cutoff , DEC ) ;
Serial . print ( F ( " Filter Resonance " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . filter_resonance , DEC ) ;
Serial . print ( F ( " Sound Intensity " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . sound_intensity , DEC ) ;
Serial . print ( F ( " Panorama " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . pan , DEC ) ;
Serial . print ( F ( " Transpose " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . transpose , DEC ) ;
Serial . print ( F ( " Tune " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . tune , DEC ) ;
Serial . print ( F ( " Polyphony " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . polyphony , DEC ) ;
Serial . print ( F ( " Engine " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . engine , DEC ) ;
Serial . print ( F ( " Mono/Poly " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . monopoly , DEC ) ;
Serial . print ( F ( " Note Refresh " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . note_refresh , DEC ) ;
Serial . print ( F ( " Pitchbend Range " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . pb_range , DEC ) ;
Serial . print ( F ( " Pitchbend Step " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . pb_step , DEC ) ;
Serial . print ( F ( " Modwheel Range " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . mw_range , DEC ) ;
Serial . print ( F ( " Modwheel Assign " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . mw_assign , DEC ) ;
Serial . print ( F ( " Modwheel Mode " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . mw_mode , DEC ) ;
Serial . print ( F ( " Footctrl Range " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . fc_range , DEC ) ;
Serial . print ( F ( " Footctrl Assign " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . fc_assign , DEC ) ;
Serial . print ( F ( " Footctrl Mode " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . fc_mode , DEC ) ;
Serial . print ( F ( " BreathCtrl Range " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . bc_range , DEC ) ;
Serial . print ( F ( " Breathctrl Assign " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . bc_assign , DEC ) ;
Serial . print ( F ( " Breathctrl Mode " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . bc_mode , DEC ) ;
Serial . print ( F ( " Aftertouch Range " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . at_range , DEC ) ;
Serial . print ( F ( " Aftertouch Assign " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . at_range , DEC ) ;
Serial . print ( F ( " Aftertouch Mode " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . at_mode , DEC ) ;
Serial . print ( F ( " Portamento Mode " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . portamento_mode , DEC ) ;
Serial . print ( F ( " Portamento Glissando " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . portamento_glissando , DEC ) ;
Serial . print ( F ( " Portamento Time " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . portamento_time , DEC ) ;
Serial . print ( F ( " OP Enabled " ) ) ; Serial . println ( configuration . dexed [ instance_id ] . op_enabled , DEC ) ;
Serial . flush ( ) ;
}
Serial . println ( ) ;
Serial . flush ( ) ;
}
void show_patch ( uint8_t instance_id )
{
char vn [ VOICE_NAME_LEN ] ;
Serial . print ( F ( " INSTANCE " ) ) ;
Serial . println ( instance_id , DEC ) ;
memset ( vn , 0 , sizeof ( vn ) ) ;
Serial . println ( F ( " +==========================================================================================================+ " ) ) ;
for ( int8_t i = 5 ; i > = 0 ; - - i )
{
Serial . println ( F ( " +==========================================================================================================+ " ) ) ;
Serial . print ( F ( " | OP " ) ) ;
Serial . print ( 6 - i , DEC ) ;
Serial . println ( F ( " | " ) ) ;
Serial . println ( F ( " +======+======+======+======+======+======+======+======+================+================+================+ " ) ) ;
Serial . println ( F ( " | R1 | R2 | R3 | R4 | L1 | L2 | L3 | L4 | LEV_SCL_BRK_PT | SCL_LEFT_DEPTH | SCL_RGHT_DEPTH | " ) ) ;
Serial . println ( F ( " +------+------+------+------+------+------+------+------+----------------+----------------+----------------+ " ) ) ;
Serial . print ( " | " ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_R1 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_R2 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_R3 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_R4 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_L1 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_L2 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_L3 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_EG_L4 ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_LEV_SCL_BRK_PT ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_SCL_LEFT_DEPTH ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_SCL_RGHT_DEPTH ] ) ;
Serial . println ( F ( " | " ) ) ;
Serial . println ( F ( " +======+======+======+======+======+===+==+==+===+======+====+========+==+====+=======+===+================+ " ) ) ;
Serial . println ( F ( " | SCL_L_CURVE | SCL_R_CURVE | RT_SCALE | AMS | KVS | OUT_LEV | OP_MOD | FRQ_C | FRQ_F | DETUNE | " ) ) ;
Serial . println ( F ( " +-------------+-------------+----------+-----+-----+---------+--------+-------+-------+--------------------+ " ) ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_SCL_LEFT_CURVE ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_SCL_RGHT_CURVE ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_OSC_RATE_SCALE ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_AMP_MOD_SENS ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_KEY_VEL_SENS ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_OUTPUT_LEV ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_OSC_MODE ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_FREQ_COARSE ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_FREQ_FINE ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ ( i * 21 ) + DEXED_OP_OSC_DETUNE ] ) ;
Serial . println ( F ( " | " ) ) ;
}
Serial . println ( F ( " +=======+=====+=+=======+===+===+======++====+==+==+====+====+==+======+======+=====+=+====================+ " ) ) ;
Serial . println ( F ( " | PR1 | PR2 | PR3 | PR4 | PL1 | PL2 | PL3 | PL4 | ALG | FB | OKS | TRANSPOSE | " ) ) ;
Serial . println ( F ( " +-------+-------+-------+-------+-------+-------+-------+-------+------+------+-----+----------------------+ " ) ) ;
Serial . print ( F ( " | " ) ) ;
for ( int8_t i = 0 ; i < 8 ; i + + )
{
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + i ] ) ;
Serial . print ( F ( " | " ) ) ;
}
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_ALGORITHM ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_FEEDBACK ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_OSC_KEY_SYNC ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_TRANSPOSE ] ) ;
Serial . println ( F ( " | " ) ) ;
Serial . println ( F ( " +=======+=+=====+===+===+=====+=+=======+=======+==+====+=====+=+======++=====+=====+======================+ " ) ) ;
Serial . println ( F ( " | LFO SPD | LFO DLY | LFO PMD | LFO AMD | LFO SYNC | LFO WAVE | LFO PMS | NAME | " ) ) ;
Serial . println ( F ( " +---------+---------+---------+---------+----------+----------+---------+----------------------------------+ " ) ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_LFO_SPEED ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_LFO_DELAY ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_DEP ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_LFO_AMP_MOD_DEP ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_LFO_SYNC ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_LFO_WAVE ] ) ;
Serial . print ( F ( " | " ) ) ;
SerialPrintFormatInt3 ( MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_LFO_PITCH_MOD_SENS ] ) ;
Serial . print ( F ( " | " ) ) ;
strncpy ( vn , ( char * ) & MicroDexed [ instance_id ] - > data [ DEXED_VOICE_OFFSET + DEXED_NAME ] , VOICE_NAME_LEN - 1 ) ;
Serial . print ( vn ) ;
Serial . println ( F ( " | " ) ) ;
Serial . println ( F ( " +=========+=========+=========+=========+==========+==========+=========+==================================+ " ) ) ;
Serial . println ( F ( " +==========================================================================================================+ " ) ) ;
}
void SerialPrintFormatInt3 ( uint8_t num )
{
char buf [ 4 ] ;
sprintf ( buf , " %3d " , num ) ;
Serial . print ( buf ) ;
}
# endif