Next try for a Chorus (modulated delay).

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

@ -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("<setup end>"));

@ -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;

@ -22,6 +22,7 @@
*/
#include <Arduino.h>
#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

@ -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

@ -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)

Loading…
Cancel
Save