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