Next try for a Chorus (modulated delay).

Fixed distortion due to too high loudness (volume) inside mdaEPiano.
master
Holger Wirtz 6 years ago
parent af801cb02c
commit 3f72a986d5
  1. 8
      MicroMDAEPiano.ino
  2. 6
      config.h
  3. 113
      effect_modulated_chorus.cpp
  4. 7
      effect_modulated_chorus.h
  5. 3
      mdaEPiano.cpp

@ -228,18 +228,22 @@ void setup()
Serial.print(audio_block_time_us); Serial.print(audio_block_time_us);
Serial.println(F("ms)")); 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")); Serial.println(F("AudioModulatedEffectChorus - right channel begin failed"));
while (1); 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")); Serial.println(F("AudioModulatedEffectChorus - left channel begin failed"));
while (1); while (1);
} }
// chorus modulation fixed
mod_sine1.amplitude(1.0); mod_sine1.amplitude(1.0);
mod_sine1.frequency(5.0); mod_sine1.frequency(5.0);
mod_sine1.phase(0); mod_sine1.phase(0);
// chorus level fixed
mixer_r.gain(2, 1.0);
mixer_l.gain(2, 1.0);
AudioInterrupts(); AudioInterrupts();

@ -61,7 +61,6 @@
#define SAMPLE_RATE 44100 #define SAMPLE_RATE 44100
#define REDUCE_LOUDNESS 0 #define REDUCE_LOUDNESS 0
#define USE_XFADE_DATA 1 #define USE_XFADE_DATA 1
#define NUM_CHORUS 2
//************************************************************************************************* //*************************************************************************************************
//* DEBUG OUTPUT SETTINGS //* DEBUG OUTPUT SETTINGS
@ -237,6 +236,10 @@
#define ENC_CHORUS_DELAY_MAX 20 #define ENC_CHORUS_DELAY_MAX 20
#define ENC_CHORUS_DELAY_DEFAULT 15 #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_MIN 0
#define ENC_CHORUS_LEVEL_MAX 99 #define ENC_CHORUS_LEVEL_MAX 99
#define ENC_CHORUS_LEVEL_DEFAULT 50 #define ENC_CHORUS_LEVEL_DEFAULT 50
@ -326,6 +329,7 @@ struct config_t {
uint8_t reverb_level; uint8_t reverb_level;
uint8_t chorus_frequency; uint8_t chorus_frequency;
uint8_t chorus_delay; uint8_t chorus_delay;
uint8_t chorus_intensity;
uint8_t chorus_level; uint8_t chorus_level;
uint8_t bass_lr_level; uint8_t bass_lr_level;
uint8_t bass_mono_level; uint8_t bass_mono_level;

@ -22,6 +22,7 @@
*/ */
#include <Arduino.h> #include <Arduino.h>
#include "limits.h"
#include "effect_modulated_chorus.h" #include "effect_modulated_chorus.h"
/******************************************************************/ /******************************************************************/
@ -32,13 +33,11 @@
// 140219 - correct storage class (not static) // 140219 - correct storage class (not static)
// 190527 - adding modulation input (by Holger Wirtz) // 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 #if 0
Serial.print("AudioModulatedEffectChorus.begin(Chorus delay line length = "); Serial.print("AudioModulatedEffectChorus.begin(Chorus delay line length = ");
Serial.print(d_length); Serial.print(d_length);
Serial.print(", n_chorus = ");
Serial.print(n_chorus);
Serial.println(")"); Serial.println(")");
#endif #endif
@ -52,78 +51,102 @@ boolean AudioModulatedEffectChorus::begin(short *delayline, int d_length, int n_
if (d_length < 10) { if (d_length < 10) {
return (false); return (false);
} }
if (n_chorus < 1) {
return (false);
}
l_delayline = delayline; l_delayline = delayline;
delay_length = d_length / 2; delay_length = d_length;
num_chorus = n_chorus; delay_length_half = d_length / 2;
return (true); return (true);
} }
void AudioModulatedEffectChorus::voices(int n_chorus)
{
num_chorus = n_chorus;
}
//int last_idx = 0; //int last_idx = 0;
void AudioModulatedEffectChorus::update(void) void AudioModulatedEffectChorus::update(void)
{ {
audio_block_t *block; audio_block_t *block;
audio_block_t *modulation; audio_block_t *modulation;
short *bp; short *bp;
int sum; short *mp;
int c_idx; float mod_idx;
int x1;
if (l_delayline == NULL)return; 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); block = receiveWritable(0);
if (block) { if (block)
{
bp = block->data; 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++; l_circ_idx++;
if (l_circ_idx >= delay_length) { if (l_circ_idx >= delay_length)
{
l_circ_idx = 0; 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); transmit(block, 0);
release(block); release(block);
} }
return; */
}
// L E F T C H A N N E L
block = receiveWritable(0); block = receiveWritable(0);
modulation = receiveReadOnly(1); modulation = receiveReadOnly(1);
if (block) { if (block && modulation)
{
bp = block->data; bp = block->data;
uint32_t tmp = delay_length / (num_chorus - 1) - 1; mp = modulation->data;
for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
l_circ_idx++; for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
if (l_circ_idx >= delay_length) { {
if (l_circ_idx >= delay_length)
l_circ_idx = 0; 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; else
sum = 0; {
c_idx = l_circ_idx; x2 = x1 + 1;
for (int k = 0; k < num_chorus; k++) { y2 = *(block->data + x2);
sum += l_delayline[c_idx];
if (num_chorus > 1)c_idx -= tmp;
if (c_idx < 0) {
c_idx += delay_length;
}
} }
*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 // transmit the block

@ -41,20 +41,19 @@ class AudioModulatedEffectChorus :
{ {
public: public:
AudioModulatedEffectChorus(void): 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); virtual void update(void);
void voices(int n_chorus);
private: private:
audio_block_t *inputQueueArray[2]; audio_block_t *inputQueueArray[2];
short *l_delayline; short *l_delayline;
short l_circ_idx; short l_circ_idx;
int num_chorus;
int delay_length; int delay_length;
int delay_length_half;
}; };
#endif #endif

@ -252,7 +252,8 @@ void mdaEPiano::setOverdrive(float value)
void mdaEPiano::setLoudness(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) void mdaEPiano::setParameter(int32_t index, float value)

Loading…
Cancel
Save