|
|
|
@ -46,6 +46,8 @@ boolean AudioEffectModulatedDelay::begin(short *delayline, int d_length) |
|
|
|
|
|
|
|
|
|
_delayline = NULL; |
|
|
|
|
_delay_length = 0; |
|
|
|
|
_delay_offset = 0.0; |
|
|
|
|
_modulation_intensity = 0.0; |
|
|
|
|
_circ_idx = 0; |
|
|
|
|
|
|
|
|
|
if (delayline == NULL) { |
|
|
|
@ -56,7 +58,13 @@ boolean AudioEffectModulatedDelay::begin(short *delayline, int d_length) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_delayline = delayline; |
|
|
|
|
_delay_length = _max_delay_length = d_length; |
|
|
|
|
_delay_length = d_length; |
|
|
|
|
|
|
|
|
|
#ifdef CHORUS_INTERPOLATION_MODE |
|
|
|
|
spline = new Spline; |
|
|
|
|
spline->setPoints(x, y, int(CHORUS_INTERPOLATION_WINDOW_SIZE)); |
|
|
|
|
spline->setDegree(CHORUS_INTERPOLATION_MODE); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
return (true); |
|
|
|
|
} |
|
|
|
@ -81,9 +89,7 @@ void AudioEffectModulatedDelay::update(void) |
|
|
|
|
float mod_fraction; |
|
|
|
|
#ifdef CHORUS_INTERPOLATION_MODE |
|
|
|
|
int8_t j; |
|
|
|
|
float x[CHORUS_INTERPOLATION_WINDOW_SIZE]; |
|
|
|
|
float y[CHORUS_INTERPOLATION_WINDOW_SIZE]; |
|
|
|
|
Spline spline(x, y, CHORUS_INTERPOLATION_WINDOW_SIZE, CHORUS_INTERPOLATION_MODE); |
|
|
|
|
uint8_t c; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
bp = block->data; |
|
|
|
@ -96,16 +102,15 @@ void AudioEffectModulatedDelay::update(void) |
|
|
|
|
_circ_idx = 0; |
|
|
|
|
_delayline[_circ_idx] = *bp; |
|
|
|
|
|
|
|
|
|
// Calculate modulation index as a float, for interpolation later.
|
|
|
|
|
// Calculate the modulation index as a float in the interval [-1.0,1.0] for interpolation later.
|
|
|
|
|
// The index is located around the half of the delay length multiplied by the current amount of the modulator
|
|
|
|
|
mod_idx = *mp * float(_delay_length >> 1); |
|
|
|
|
mod_idx = _delay_offset + ((float(*mp) / SHRT_MAX) * _modulation_intensity); |
|
|
|
|
mod_fraction = modff(mod_idx, &mod_number); |
|
|
|
|
#ifdef CHORUS_INTERPOLATION_MODE |
|
|
|
|
// Spline interpolation
|
|
|
|
|
// Generate a an array with the size of CHORUS_INTERPOLATION_WINDOW_SIZE of x/y values around mod_idx for interpolation
|
|
|
|
|
uint8_t c = 0; |
|
|
|
|
int16_t c_mod_idx = _circ_idx - int(round(mod_idx)); // This is the pointer to the value in the circular buffer at the current modulation index
|
|
|
|
|
for (j = (CHORUS_INTERPOLATION_WINDOW_SIZE / -2); j <= (CHORUS_INTERPOLATION_WINDOW_SIZE / 2); j++) |
|
|
|
|
for (j = (CHORUS_INTERPOLATION_WINDOW_SIZE / -2), c = 0; j <= (CHORUS_INTERPOLATION_WINDOW_SIZE / 2); j++, c++) |
|
|
|
|
{ |
|
|
|
|
int16_t jc_mod_idx = (c_mod_idx + j) % _delay_length; // The modulation index pointer plus the value of the current window pointer
|
|
|
|
|
if (jc_mod_idx < 0) // check for negative offsets and correct them
|
|
|
|
@ -113,9 +118,8 @@ void AudioEffectModulatedDelay::update(void) |
|
|
|
|
else |
|
|
|
|
y[c] = float(_delayline[jc_mod_idx]); |
|
|
|
|
x[c] = float(j); |
|
|
|
|
c++; |
|
|
|
|
} |
|
|
|
|
*bp = int(round(spline.value(mod_fraction))); // use spline interpolated value
|
|
|
|
|
*bp = int(round(spline->value(mod_fraction))); // use spline interpolated value
|
|
|
|
|
#else |
|
|
|
|
// Simple interpolation
|
|
|
|
|
int16_t c_mod_idx = (_circ_idx + int(round(mod_idx))) % _delay_length; |
|
|
|
@ -131,7 +135,12 @@ void AudioEffectModulatedDelay::update(void) |
|
|
|
|
value1 = _delayline[c_mod_idx - 1]; |
|
|
|
|
value2 = _delayline[c_mod_idx]; |
|
|
|
|
} |
|
|
|
|
*bp = int(round(mod_fraction * value1 + (1.0 - mod_fraction) * value2)); |
|
|
|
|
|
|
|
|
|
if (mod_fraction < 0) |
|
|
|
|
*bp = int(round((1.0 + mod_fraction) * value1 + fabs(mod_fraction) * value2)); |
|
|
|
|
else |
|
|
|
|
*bp = int(round(mod_fraction * value1 + (1.0 - mod_fraction) * value2)); |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
bp++; // next audio data
|
|
|
|
|
mp++; // next modulation data
|
|
|
|
@ -149,7 +158,25 @@ void AudioEffectModulatedDelay::update(void) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AudioEffectModulatedDelay::setDelay(float milliseconds) |
|
|
|
|
float AudioEffectModulatedDelay::offset(float offset_value) |
|
|
|
|
{ |
|
|
|
|
_delay_length = min(AUDIO_SAMPLE_RATE * milliseconds / 500, _max_delay_length); |
|
|
|
|
uint16_t offset_frames = (offset_value / 1000) * AUDIO_SAMPLE_RATE; |
|
|
|
|
if (offset_frames > _delay_length * MODULATION_MAX_FACTOR) |
|
|
|
|
_delay_offset = _delay_length * MODULATION_MAX_FACTOR; |
|
|
|
|
else if (offset_frames <= _delay_length * (1 - MODULATION_MAX_FACTOR)) |
|
|
|
|
_delay_offset = _delay_length * (1 - MODULATION_MAX_FACTOR); |
|
|
|
|
else |
|
|
|
|
_delay_offset = offset_frames; |
|
|
|
|
|
|
|
|
|
return (offset_frames / AUDIO_SAMPLE_RATE * 1000); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void AudioEffectModulatedDelay::intensity(float intensity_value) |
|
|
|
|
{ |
|
|
|
|
if (intensity_value > 1.0) |
|
|
|
|
intensity_value = 1.0; |
|
|
|
|
else if (intensity_value < 0.0) |
|
|
|
|
intensity_value = 0.0; |
|
|
|
|
|
|
|
|
|
_modulation_intensity = intensity_value * (1 - MODULATION_MAX_FACTOR) * 2 * _delay_length; |
|
|
|
|
} |
|
|
|
|