From 3f72a986d55d09bf27fabc90291538ac06fba82e Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Wed, 29 May 2019 12:56:46 +0200 Subject: [PATCH] Next try for a Chorus (modulated delay). Fixed distortion due to too high loudness (volume) inside mdaEPiano. --- MicroMDAEPiano.ino | 10 +++- config.h | 6 +- effect_modulated_chorus.cpp | 113 ++++++++++++++++++++++-------------- effect_modulated_chorus.h | 7 +-- mdaEPiano.cpp | 3 +- 5 files changed, 85 insertions(+), 54 deletions(-) diff --git a/MicroMDAEPiano.ino b/MicroMDAEPiano.ino index 379c709..14844f4 100644 --- a/MicroMDAEPiano.ino +++ b/MicroMDAEPiano.ino @@ -228,19 +228,23 @@ void setup() Serial.print(audio_block_time_us); Serial.println(F("ms)")); - if (!modchorus_r.begin(r_delayline, CHORUS_DELAY_LENGTH, NUM_CHORUS)) { + if (!modchorus_r.begin(r_delayline, CHORUS_DELAY_LENGTH)) { Serial.println(F("AudioModulatedEffectChorus - right channel begin failed")); while (1); } - if (!modchorus_l.begin(l_delayline, CHORUS_DELAY_LENGTH, NUM_CHORUS)) { + if (!modchorus_l.begin(l_delayline, CHORUS_DELAY_LENGTH)) { Serial.println(F("AudioModulatedEffectChorus - left channel begin failed")); while (1); } + // chorus modulation fixed mod_sine1.amplitude(1.0); mod_sine1.frequency(5.0); mod_sine1.phase(0); - + // chorus level fixed + mixer_r.gain(2, 1.0); + mixer_l.gain(2, 1.0); + AudioInterrupts(); Serial.println(F("")); diff --git a/config.h b/config.h index 75d1dad..8a4c9d8 100644 --- a/config.h +++ b/config.h @@ -61,7 +61,6 @@ #define SAMPLE_RATE 44100 #define REDUCE_LOUDNESS 0 #define USE_XFADE_DATA 1 -#define NUM_CHORUS 2 //************************************************************************************************* //* DEBUG OUTPUT SETTINGS @@ -237,6 +236,10 @@ #define ENC_CHORUS_DELAY_MAX 20 #define ENC_CHORUS_DELAY_DEFAULT 15 // +#define ENC_CHORUS_INTENSITY_MIN 0 +#define ENC_CHORUS_INTENSITY_MAX 100 +#define ENC_CHORUS_INTENSITY_DEFAULT 50 +// #define ENC_CHORUS_LEVEL_MIN 0 #define ENC_CHORUS_LEVEL_MAX 99 #define ENC_CHORUS_LEVEL_DEFAULT 50 @@ -326,6 +329,7 @@ struct config_t { uint8_t reverb_level; uint8_t chorus_frequency; uint8_t chorus_delay; + uint8_t chorus_intensity; uint8_t chorus_level; uint8_t bass_lr_level; uint8_t bass_mono_level; diff --git a/effect_modulated_chorus.cpp b/effect_modulated_chorus.cpp index 4f3c887..c5d8e9e 100644 --- a/effect_modulated_chorus.cpp +++ b/effect_modulated_chorus.cpp @@ -22,6 +22,7 @@ */ #include +#include "limits.h" #include "effect_modulated_chorus.h" /******************************************************************/ @@ -32,13 +33,11 @@ // 140219 - correct storage class (not static) // 190527 - adding modulation input (by Holger Wirtz) -boolean AudioModulatedEffectChorus::begin(short *delayline, int d_length, int n_chorus) +boolean AudioModulatedEffectChorus::begin(short *delayline, int d_length) { #if 0 Serial.print("AudioModulatedEffectChorus.begin(Chorus delay line length = "); Serial.print(d_length); - Serial.print(", n_chorus = "); - Serial.print(n_chorus); Serial.println(")"); #endif @@ -52,78 +51,102 @@ boolean AudioModulatedEffectChorus::begin(short *delayline, int d_length, int n_ if (d_length < 10) { return (false); } - if (n_chorus < 1) { - return (false); - } l_delayline = delayline; - delay_length = d_length / 2; - num_chorus = n_chorus; + delay_length = d_length; + delay_length_half = d_length / 2; return (true); } -void AudioModulatedEffectChorus::voices(int n_chorus) -{ - num_chorus = n_chorus; -} - //int last_idx = 0; void AudioModulatedEffectChorus::update(void) { audio_block_t *block; audio_block_t *modulation; short *bp; - int sum; - int c_idx; - - if (l_delayline == NULL)return; + short *mp; + float mod_idx; + int x1; + int x2; + int y1; + int y2; + + if (l_delayline == NULL) + return; - // do passthru - // It stores the unmodified data in the delay line so that - // it isn't as likely to click - if (num_chorus <= 1) { - // Just passthrough + /* block = receiveWritable(0); - if (block) { + if (block) + { bp = block->data; - for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { + uint32_t tmp = delay_length / (num_chorus - 1) - 1; + for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) + { l_circ_idx++; - if (l_circ_idx >= delay_length) { + if (l_circ_idx >= delay_length) + { l_circ_idx = 0; } - l_delayline[l_circ_idx] = *bp++; + l_delayline[l_circ_idx] = *bp; + sum = 0; + c_idx = l_circ_idx; + for (int k = 0; k < num_chorus; k++) + { + sum += l_delayline[c_idx]; + if (num_chorus > 1)c_idx -= tmp; + if (c_idx < 0) + { + c_idx += delay_length; + } + } + bp++ = sum / num_chorus; } + // transmit the block transmit(block, 0); release(block); } - return; - } - - // L E F T C H A N N E L + */ block = receiveWritable(0); modulation = receiveReadOnly(1); - if (block) { + if (block && modulation) + { bp = block->data; - uint32_t tmp = delay_length / (num_chorus - 1) - 1; - for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) { - l_circ_idx++; - if (l_circ_idx >= delay_length) { + mp = modulation->data; + + for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) + { + if (l_circ_idx >= delay_length) l_circ_idx = 0; + l_delayline[l_circ_idx] = *bp; // write signal into circular buffer + + mod_idx = float(*mp) / SHRT_MAX * delay_length_half + l_circ_idx; // calculate index with modulation as a float + + if (mod_idx > delay_length) + mod_idx = mod_idx - delay_length; + else if (mod_idx < 0) + mod_idx = delay_length + mod_idx; + + // linear interpolation + x1 = int(mod_idx); + y1 = *(block->data + x1); + if (x1 + 1 > delay_length) + { + x2 = 0; + y2 = *block->data; } - l_delayline[l_circ_idx] = *bp; - sum = 0; - c_idx = l_circ_idx; - for (int k = 0; k < num_chorus; k++) { - sum += l_delayline[c_idx]; - if (num_chorus > 1)c_idx -= tmp; - if (c_idx < 0) { - c_idx += delay_length; - } + else + { + x2 = x1 + 1; + y2 = *(block->data + x2); } - *bp++ = sum / num_chorus; + *bp = (*bp >> 1) + (int((float(y2 - y1) / (x2 - x1) * (mod_idx - x1) + y1) + 0.5) >> 1); // mix original signal 1:1 with modulated signal + + bp++; + mp++; + l_circ_idx++; } // transmit the block diff --git a/effect_modulated_chorus.h b/effect_modulated_chorus.h index a9f2acb..93698d1 100644 --- a/effect_modulated_chorus.h +++ b/effect_modulated_chorus.h @@ -41,20 +41,19 @@ class AudioModulatedEffectChorus : { public: AudioModulatedEffectChorus(void): - AudioStream(2, inputQueueArray), num_chorus(2) + AudioStream(2, inputQueueArray) { } - boolean begin(short *delayline, int delay_length, int n_chorus); + boolean begin(short *delayline, int delay_length); virtual void update(void); - void voices(int n_chorus); private: audio_block_t *inputQueueArray[2]; short *l_delayline; short l_circ_idx; - int num_chorus; int delay_length; + int delay_length_half; }; #endif diff --git a/mdaEPiano.cpp b/mdaEPiano.cpp index f419207..bf000f3 100644 --- a/mdaEPiano.cpp +++ b/mdaEPiano.cpp @@ -252,7 +252,8 @@ void mdaEPiano::setOverdrive(float value) void mdaEPiano::setLoudness(float value) { - volume = value * 0.32258; // 0.00002 * 127^2 + //volume = value * 0.32258; // 0.00002 * 127^2 + volume = value * 0.2; // 0.00002 * 127^2 } void mdaEPiano::setParameter(int32_t index, float value)