diff --git a/MicroDexed.ino b/MicroDexed.ino index 9df2d4f..4d024e6 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -41,10 +41,8 @@ #include "UI.hpp" #include "source_microdexed.h" +// Audio engines AudioAnalyzePeak peak1; - -//AudioPlayQueue queue1; - AudioSourceMicroDexed* MicroDexed[NUM_DEXED]; AudioEffectDelay delay1; AudioEffectModulatedDelay modchorus; @@ -54,68 +52,71 @@ AudioMixer4 master_mixer_r; AudioMixer4 master_mixer_l; AudioAmplifier volume_r; AudioAmplifier volume_l; +AudioAmplifier modchorus_inverter; #if defined(AUDIO_DEVICE_USB) AudioOutputUSB usb1; #endif AudioEffectStereoMono stereomono1; -AudioConnection patchCord5(modulator, 0, modchorus, 1); + +// Audio connections +AudioConnection patchCord1(modulator, 0, modchorus, 1); #if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT AudioFilterBiquad modchorus_filter; -AudioConnection patchCord6(modchorus, modchorus_filter); -AudioConnection patchCord7(modchorus_filter, 0, master_mixer_r, 3); -AudioConnection patchCord8(modchorus_filter, 0, master_mixer_l, 3); +AudioConnection patchCord2(modchorus, modchorus_filter); +AudioConnection patchCord3(modchorus_filter, 0, master_mixer_r, 3); +AudioConnection patchCord4(modchorus_filter, modchorus_inverter); +AudioConnection patchCord5(modchorus_inverter, 0, master_mixer_l, 3); #else -AudioConnection patchCord9(modchorus, 0, master_mixer_r, 3); -AudioConnection patchCord10(modchorus, 0, master_mixer_l, 3); +AudioConnection patchCord6(modchorus, 0, master_mixer_r, 3); +AudioConnection patchCord7(modchorus, modchorus_inverter); +AudioConnection patchCord8(modchorus_inverter, 0, master_mixer_l, 3); #endif #if defined(USE_REVERB) AudioEffectFreeverbStereo freeverbs1; -AudioConnection patchCord13(freeverbs1, 0, master_mixer_r, 1); -AudioConnection patchCord14(freeverbs1, 1, master_mixer_l, 1); +AudioConnection patchCord9(freeverbs1, 0, master_mixer_r, 1); +AudioConnection patchCord10(freeverbs1, 1, master_mixer_l, 1); #endif -AudioConnection patchCord15(delay_fb_mixer, delay1); -AudioConnection patchCord16(delay1, 0, delay_fb_mixer, 1); -AudioConnection patchCord17(delay1, 0, master_mixer_r, 2); -AudioConnection patchCord18(delay1, 0, master_mixer_l, 2); -AudioConnection patchCord19(master_mixer_r, volume_r); -AudioConnection patchCord20(master_mixer_l, volume_l); -AudioConnection patchCord21(volume_r, 0, stereomono1, 0); -AudioConnection patchCord22(volume_l, 0, stereomono1, 1); +AudioConnection patchCord11(delay_fb_mixer, delay1); +AudioConnection patchCord12(delay1, 0, delay_fb_mixer, 1); +AudioConnection patchCord13(delay1, 0, master_mixer_r, 2); +AudioConnection patchCord14(delay1, 0, master_mixer_l, 2); +AudioConnection patchCord15(master_mixer_r, volume_r); +AudioConnection patchCord16(master_mixer_l, volume_l); +AudioConnection patchCord17(volume_r, 0, stereomono1, 0); +AudioConnection patchCord18(volume_l, 0, stereomono1, 1); #ifdef AUDIO_DEVICE_USB -AudioConnection patchCord23(stereomono1, 0, usb1, 0); -AudioConnection patchCord24(stereomono1, 1, usb1, 1); +AudioConnection patchCord19(stereomono1, 0, usb1, 0); +AudioConnection patchCord20(stereomono1, 1, usb1, 1); #endif #if defined(TEENSY_AUDIO_BOARD) AudioOutputI2S i2s1; -AudioConnection patchCord25(stereomono1, 0, i2s1, 0); -AudioConnection patchCord26(stereomono1, 1, i2s1, 1); +AudioConnection patchCord21(stereomono1, 0, i2s1, 0); +AudioConnection patchCord22(stereomono1, 1, i2s1, 1); AudioControlSGTL5000 sgtl5000_1; #elif defined (I2S_AUDIO_ONLY) AudioOutputI2S i2s1; -AudioConnection patchCord27(stereomono1, 0, i2s1, 0); -AudioConnection patchCord28(stereomono1, 1, i2s1, 1); +AudioConnection patchCord23(stereomono1, 0, i2s1, 0); +AudioConnection patchCord24(stereomono1, 1, i2s1, 1); #elif defined(TGA_AUDIO_BOARD) AudioOutputI2S i2s1; -AudioConnection patchCord29(stereomono1, 0, i2s1, 0); -AudioConnection patchCord30(stereomono1, 1, i2s1, 1); +AudioConnection patchCord25(stereomono1, 0, i2s1, 0); +AudioConnection patchCord26(stereomono1, 1, i2s1, 1); AudioControlWM8731master wm8731_1; #elif defined(PT8211_AUDIO) AudioOutputPT8211 pt8211_1; -AudioConnection patchCord31(stereomono1, 0, pt8211_1, 0); -AudioConnection patchCord32(stereomono1, 1, pt8211_1, 1); +AudioConnection patchCord27(stereomono1, 0, pt8211_1, 0); +AudioConnection patchCord28(stereomono1, 1, pt8211_1, 1); #elif defined(TEENSY_DAC_SYMMETRIC) AudioOutputAnalogStereo dacOut; AudioMixer4 invMixer; -AudioConnection patchCord33(stereomono1, 0, dacOut , 0); -AudioConnection patchCord34(stereomono1, 1, invMixer, 0); -AudioConnection patchCord35(invMixer, 0, dacOut , 1); +AudioConnection patchCord29(stereomono1, 0, dacOut , 0); +AudioConnection patchCord30(stereomono1, 1, invMixer, 0); +AudioConnection patchCord31(invMixer, 0, dacOut , 1); #else AudioOutputAnalogStereo dacOut; -AudioConnection patchCord36(stereomono1, 0, dacOut, 0); -AudioConnection patchCord37(stereomono1, 1, dacOut, 1); +AudioConnection patchCord32(stereomono1, 0, dacOut, 0); +AudioConnection patchCord33(stereomono1, 1, dacOut, 1); #endif - -//Dexed* MicroDexed[NUM_DEXED]; AudioConnection * dynamicConnections[NUM_DEXED * 7]; int nDynamic = 0; @@ -133,7 +134,6 @@ void create_audio_connections(AudioSourceMicroDexed &d) } bool sd_card_available = false; - uint8_t max_loaded_banks = 0; char bank_name[BANK_NAME_LEN]; char voice_name[VOICE_NAME_LEN]; @@ -194,15 +194,7 @@ void setup() Serial.println(F("NO LCD DISPLAY ENABLED!")); #endif - for (uint8_t i = 0; i < NUM_DEXED; i++) - { - Serial.print(F("Creating MicroDexed engine ")); - Serial.println(i, DEC); - MicroDexed[i] = new AudioSourceMicroDexed(SAMPLE_RATE); - create_audio_connections(*MicroDexed[i]); - } - //microdexed1.setDexeds(NUM_DEXED, MicroDexed); - delay(220); + delay(220); // necessary, because before this time no serial output is done :( Serial.println(F("MicroDexed based on https://github.com/asb2m10/dexed")); Serial.println(F("(c)2018,2019 H. Wirtz ")); @@ -213,6 +205,14 @@ void setup() initial_values_from_eeprom(); + for (uint8_t i = 0; i < NUM_DEXED; i++) + { + Serial.print(F("Creating MicroDexed engine ")); + Serial.println(i, DEC); + MicroDexed[i] = new AudioSourceMicroDexed(SAMPLE_RATE); + create_audio_connections(*MicroDexed[i]); + } + setup_midi_devices(); // start audio card @@ -313,8 +313,9 @@ void setup() change_disp_sd(true); #endif // Init effects + memset(delayline, 0, MOD_DELAY_SAMPLE_BUFFER); if (!modchorus.begin(delayline, MOD_DELAY_SAMPLE_BUFFER)) { - Serial.println(F("AudioEffectModulatedDelay - right channel begin failed")); + Serial.println(F("AudioEffectModulatedDelay - begin failed")); while (1); } #ifdef DEBUG @@ -326,23 +327,35 @@ void setup() master_mixer_l.gain(0, 1.0); #ifdef USE_REVERB - freeverbs1.roomsize(configuration.reverb_roomsize / 100.0); - freeverbs1.damping(configuration.reverb_damping / 100.0); + // INIT REVERB + freeverbs1.roomsize(mapfloat(configuration.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0)); + freeverbs1.damping(mapfloat(configuration.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0)); + master_mixer_r.gain(1, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); + master_mixer_l.gain(1, mapfloat(configuration.reverb_level, REVERB_LEVEL_MIN, REVERB_LEVEL_MAX, 0.0, 1.0)); #endif - master_mixer_r.gain(1, 0.0); - master_mixer_l.gain(1, 0.0); - - delay1.delay(0, 0.0); + // INIT DELAY + delay1.delay(0, mapfloat(configuration.delay_time, DELAY_TIME_MIN, DELAY_TIME_MAX, 0.0, float(DELAY_TIME_MAX))); // delay_fb_mixer is the feedback-adding mixer - delay_fb_mixer.gain(0, 1.0 - configuration.delay_feedback / 100.0); // original signal - delay_fb_mixer.gain(1, configuration.delay_feedback / 100.0); // amount of feedback - master_mixer_r.gain(2, 0.0); - master_mixer_l.gain(2, 0.0); + delay_fb_mixer.gain(0, 1.0 - (mapfloat(configuration.delay_feedback, DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0))); // original signal + delay_fb_mixer.gain(1, mapfloat(configuration.delay_feedback, DELAY_FEEDBACK_MIN, DELAY_FEEDBACK_MAX, 0.0, 1.0)); // amount of feedback + master_mixer_r.gain(2, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); + master_mixer_l.gain(2, mapfloat(configuration.delay_level, DELAY_LEVEL_MIN, DELAY_LEVEL_MAX, 0.0, 1.0)); - modulator.begin(MOD_WAVEFORM); + // INIT CHORUS + switch (configuration.chorus_waveform) + { + case 0: + modulator.begin(WAVEFORM_TRIANGLE); + break; + case 1: + modulator.begin(WAVEFORM_SINE); + break; + default: + modulator.begin(WAVEFORM_TRIANGLE); + } modulator.phase(0); - modulator.amplitude(0.5); + modulator.amplitude(mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); modulator.offset(0.0); #if MOD_FILTER_OUTPUT == MOD_BUTTERWORTH_FILTER_OUTPUT // Butterworth filter, 12 db/octave @@ -353,21 +366,21 @@ void setup() modchorus_filter.setLowpass(1, MOD_FILTER_CUTOFF_HZ, 1.3); modchorus_filter.setLowpass(2, MOD_FILTER_CUTOFF_HZ, 0.54); modchorus_filter.setLowpass(3, MOD_FILTER_CUTOFF_HZ, 1.3); - modchorus_filter.setLowpass(0, MOD_FILTER_CUTOFF_HZ, 0.54); - modchorus_filter.setLowpass(1, MOD_FILTER_CUTOFF_HZ, 1.3); - modchorus_filter.setLowpass(2, MOD_FILTER_CUTOFF_HZ, 0.54); - modchorus_filter.setLowpass(3, MOD_FILTER_CUTOFF_HZ, 1.3); #endif - master_mixer_r.gain(3, 0.0); - master_mixer_l.gain(3, 0.0); + if (configuration.mono == 0) + modchorus_inverter.gain(-1.0); // stereo mode + else + modchorus_inverter.gain(1.0); // mono mode + master_mixer_r.gain(3, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); + master_mixer_l.gain(3, mapfloat(configuration.chorus_level, CHORUS_LEVEL_MIN, CHORUS_LEVEL_MAX, 0.0, 1.0)); for (uint8_t i = 0; i < NUM_DEXED; i++) { - soften_filter_res[i].init(1.0); - soften_filter_cut[i].init(1.0); - MicroDexed[i]->fx.Gain = 1.0; - MicroDexed[i]->fx.Reso = 1.0; - MicroDexed[i]->fx.Cutoff = 1.0; + soften_filter_res[i].init(configuration.filter_resonance); + soften_filter_cut[i].init(configuration.filter_cutoff); + MicroDexed[i]->fx.Gain = mapfloat(configuration.loudness, LOUDNESS_MIN, LOUDNESS_MAX, 0.0, 1.0); + MicroDexed[i]->fx.Reso = mapfloat(configuration.filter_resonance, FILTER_RESONANCE_MIN, FILTER_RESONANCE_MAX, 0.0, 1.0); + MicroDexed[i]->fx.Cutoff = mapfloat(configuration.filter_cutoff, FILTER_CUTOFF_MIN, FILTER_CUTOFF_MAX, 0.0, 1.0); } // set initial volume and pan (read from EEPROM) @@ -1020,20 +1033,24 @@ void set_volume(uint8_t v, int8_t p, uint8_t m) { case 0: // stereo stereomono1.stereo(true); + modchorus_inverter.gain(-1.0); // stereo mode break; case 1: // mono both stereomono1.stereo(false); configuration.pan = 0.5; + modchorus_inverter.gain(1.0); // stereo mode break; case 2: // mono right volume_l.gain(0.0); stereomono1.stereo(false); configuration.pan = 0.5; + modchorus_inverter.gain(1.0); // stereo mode break; case 3: // mono left volume_r.gain(0.0); stereomono1.stereo(false); configuration.pan = 0.5; + modchorus_inverter.gain(1.0); // stereo mode break; } } @@ -1099,6 +1116,7 @@ void initial_values_from_eeprom(void) } #ifdef DEBUG Serial.println(); + show_configuration(); #endif if (configuration.vol > 100) @@ -1175,6 +1193,35 @@ void show_cpu_and_mem_usage(void) #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("Bank ")); Serial.println(configuration.bank, DEC); + Serial.print(F("Voice ")); Serial.println(configuration.voice, DEC); + Serial.print(F("Volume ")); Serial.println(configuration.vol, DEC); + Serial.print(F("Panorama ")); Serial.println(configuration.pan, DEC); + Serial.print(F("Mono ")); Serial.println(configuration.mono, DEC); + Serial.print(F("MIDI-Channel ")); Serial.println(configuration.midi_channel, 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("Filter Cutoff ")); Serial.println(configuration.filter_cutoff, DEC); + Serial.print(F("Filter Resonance ")); Serial.println(configuration.filter_resonance, DEC); + Serial.print(F("Loudness ")); Serial.println(configuration.loudness, DEC); + Serial.print(F("Polyphony ")); Serial.println(configuration.polyphony, DEC); + Serial.print(F("Engine ")); Serial.println(configuration.engine, DEC); + Serial.println(); +} + void show_patch(void) { uint8_t i; diff --git a/UI.hpp b/UI.hpp index 55849e5..0de373d 100644 --- a/UI.hpp +++ b/UI.hpp @@ -808,7 +808,7 @@ void UI_func_reverb_roomsize(uint8_t param) lcd.setCursor(0, 1); lcd_display_int(configuration.reverb_roomsize, 3, true, true, false); - freeverbs1.roomsize(configuration.reverb_roomsize / 100.0); + freeverbs1.roomsize(mapfloat(configuration.reverb_roomsize, REVERB_ROOMSIZE_MIN, REVERB_ROOMSIZE_MAX, 0.0, 1.0)); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -855,7 +855,7 @@ void UI_func_reverb_damping(uint8_t param) lcd.setCursor(0, 1); lcd_display_int(configuration.reverb_damping, 3, true, true, false); - freeverbs1.damping(configuration.reverb_damping / 100.0); + freeverbs1.damping(mapfloat(configuration.reverb_damping, REVERB_DAMPING_MIN, REVERB_DAMPING_MAX, 0.0, 1.0)); } if (LCDML.FUNC_close()) // ****** STABLE END ********* @@ -1120,7 +1120,7 @@ void UI_func_delay_time(uint8_t param) } else if (LCDML.BT_checkDown()) { - if (configuration.delay_time < DELAY_TIME_MAX) + if (configuration.delay_time < DELAY_TIME_MAX / 10) { configuration.delay_time += 1; } @@ -1614,10 +1614,10 @@ void UI_func_engine(uint8_t param) lcd.print(F("[MODERN]")); break; case 1: - lcd.print(F("[MARK 1 ]")); + lcd.print(F("[MARK 1]")); break; case 2: - lcd.print(F("[OPL ]")); + lcd.print(F("[OPL ]")); break; } diff --git a/config.h b/config.h index 270b2c4..71cf461 100644 --- a/config.h +++ b/config.h @@ -88,25 +88,24 @@ //************************************************************************************************* //* AUDIO SOFTWARE SETTINGS //************************************************************************************************* -// https://rechneronline.de/funktionsgraphen/ #ifndef TEENSY_AUDIO_BOARD #if AUDIO_BLOCK_SAMPLES == 64 #define AUDIO_MEM 450 #else #define AUDIO_MEM 225 #endif -#define DELAY_MAX_TIME 600 #define REDUCE_LOUDNESS 1 -#else +#else // IF TEENSY_AUDIO_BOARD #define SGTL5000_LINEOUT_LEVEL 29 #if AUDIO_BLOCK_SAMPLES == 64 #define AUDIO_MEM 900 #else #define AUDIO_MEM 450 #endif -#define DELAY_MAX_TIME 1200 +#define DELAY_MAX_TIME 600 #define REDUCE_LOUDNESS 1 #endif +#define DELAY_MAX_TIME 600 #define SAMPLE_RATE 44100 #define SOFTEN_VALUE_CHANGE_STEPS 5 @@ -310,7 +309,7 @@ #define CHORUS_LEVEL_DEFAULT 0 #define DELAY_TIME_MIN 0 -#define DELAY_TIME_MAX DELAY_MAX_TIME/10 +#define DELAY_TIME_MAX DELAY_MAX_TIME #define DELAY_TIME_DEFAULT 0 #define DELAY_FEEDBACK_MIN 0 @@ -323,11 +322,11 @@ #define FILTER_CUTOFF_MIN 0 #define FILTER_CUTOFF_MAX 100 -#define FILTER_CUTOFF_DEFAULT 0 +#define FILTER_CUTOFF_DEFAULT 100 #define FILTER_RESONANCE_MIN 0 #define FILTER_RESONANCE_MAX 100 -#define FILTER_RESONANCE_DEFAULT 0 +#define FILTER_RESONANCE_DEFAULT 100 #define LOUDNESS_MIN 0 #define LOUDNESS_MAX 100