From 91df5f84a86555239d15741a176d17ecaf85be3f Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Tue, 11 Jun 2019 13:14:48 +0200 Subject: [PATCH] Fixes for the chorus. --- config.h | 4 +- effect_modulated_delay.cpp | 40 ++++--- effect_modulated_delay.h | 6 +- old/interpolation.cpp | 209 ------------------------------------- old/interpolation.h | 79 -------------- spline.cpp | 78 ++++++++------ spline.h | 6 +- 7 files changed, 76 insertions(+), 346 deletions(-) delete mode 100644 old/interpolation.cpp delete mode 100644 old/interpolation.h diff --git a/config.h b/config.h index 009c441..d4da466 100644 --- a/config.h +++ b/config.h @@ -61,9 +61,9 @@ #define REDUCE_LOUDNESS 0 #define USE_XFADE_DATA 1 // CHORUS parameters -#define INTERPOLATION_WINDOW_SIZE 7 // use only odd numbers!!! +#define INTERPOLATION_WINDOW_SIZE 21 // use only odd numbers!!! #define INTERPOLATE_MODE 11 -#define CHORUS_WAVEFORM WAVEFORM_TRIANGLE // WAVEFORM_SINE WAVEFORM_TRIANGLE WAVEFORM_SAWTOOTH WAVEFORM_SAWTOOTH_REVERSE +#define CHORUS_WAVEFORM WAVEFORM_SINE // WAVEFORM_SINE WAVEFORM_TRIANGLE WAVEFORM_SAWTOOTH WAVEFORM_SAWTOOTH_REVERSE #define CHORUS_DELAY_LENGTH_SAMPLES (15*AUDIO_BLOCK_SAMPLES) // one AUDIO_BLOCK_SAMPLES = 2.902ms; you need doubled length, e.g. delay point is 20ms, so you need up to 40ms delay! //************************************************************************************************* diff --git a/effect_modulated_delay.cpp b/effect_modulated_delay.cpp index 0280a05..9e74d5f 100644 --- a/effect_modulated_delay.cpp +++ b/effect_modulated_delay.cpp @@ -26,7 +26,6 @@ #include "limits.h" #include "effect_modulated_delay.h" #include "spline.h" -#include "config.h" /******************************************************************/ @@ -58,8 +57,6 @@ boolean AudioEffectModulatedDelay::begin(short *delayline, int d_length) _delayline = delayline; _delay_length = _max_delay_length = d_length; - memset(_delayline, 0, sizeof(int16_t)*_delay_length); - return (true); } @@ -97,37 +94,46 @@ void AudioEffectModulatedDelay::update(void) _circ_idx = 0; _delayline[_circ_idx] = *bp; - // calculate modulation index - mod_idx = float(*mp) / SHRT_MAX * float(_delay_length / 2); // calculate an index with modulation as a float(!!!) + // Calculate modulation index as a float, for interpolation later. + // The index is located around the half of the delay length multiplied by the current amount of the modulator + mod_idx = float(*mp) / SHRT_MAX * float(_delay_length >> 1); #ifdef INTERPOLATE_MODE - // get x/y values around mod_idx + // Generate a an array with the size of INTERPOLATION_WINDOW_SIZE of x/y values around mod_idx for interpolation uint8_t c = 0; - int16_t c_mod_idx = int(mod_idx + 0.5) + _circ_idx; + int16_t c_mod_idx = _circ_idx - int(mod_idx + 0.5); // This is the pointer to the value in the circular buffer at the current modulation index for (j = INTERPOLATION_WINDOW_SIZE / -2; j <= INTERPOLATION_WINDOW_SIZE / 2; j++) { - int16_t jc_mod_idx = (c_mod_idx + j) % (_delay_length - 1); + 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) - y[c] = float(_delayline[_delay_length - 1 + jc_mod_idx]); + y[c] = float(_delayline[_delay_length + jc_mod_idx]); else y[c] = float(_delayline[jc_mod_idx]); - x[c] = float(c); + x[c] = float(j); c++; // because 42 is the answer! ;-) } - - *bp = int(s.value(mod_idx - int(mod_idx + 0.5)) + 0.5); + *bp = int(s.value(modff(mod_idx, NULL)) + 0.5); #else // No interpolation - should sound really bad... - int16_t c_mod_idx = (int(mod_idx + 0.5) + _circ_idx) % (_delay_length - 1); + int16_t c_mod_idx = (_circ_idx - int(mod_idx + 0.5)) % _delay_length; if (c_mod_idx < 0) - *bp = _delayline[_delay_length - 1 + c_mod_idx]; + *bp = _delayline[_delay_length + c_mod_idx]; else *bp = _delayline[c_mod_idx]; +/* Serial.print("mod_idx="); + Serial.print(mod_idx, 3); + Serial.print(" c_mod_idx="); + Serial.print(c_mod_idx, DEC); + Serial.print(" MODULATION="); + Serial.print(*mp, DEC); + Serial.print(" DATA="); + Serial.print(*bp, DEC); + Serial.println();*/ #endif - bp++; - mp++; - _circ_idx++; + bp++; // next audio data + mp++; // next modulation data + _circ_idx++; // next circular buffer index } } diff --git a/effect_modulated_delay.h b/effect_modulated_delay.h index 54803a0..5c395e4 100644 --- a/effect_modulated_delay.h +++ b/effect_modulated_delay.h @@ -26,7 +26,6 @@ #include "Arduino.h" #include "AudioStream.h" -#include "config.h" /*************************************************************************/ @@ -35,6 +34,9 @@ // 140219 - correct storage class (not static) // 190527 - added modulation input handling (by Holger Wirtz) + +#define MODF(n,i,f) ((i) = (int)(n), (f) = (n) - (double)(i)) + class AudioEffectModulatedDelay : public AudioStream { @@ -50,7 +52,7 @@ class AudioEffectModulatedDelay : private: audio_block_t *inputQueueArray[2]; int16_t *_delayline; - int16_t _circ_idx; + uint16_t _circ_idx; uint16_t _max_delay_length; uint16_t _delay_length; }; diff --git a/old/interpolation.cpp b/old/interpolation.cpp deleted file mode 100644 index 65340bb..0000000 --- a/old/interpolation.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* -* interpolation.h -* -* interpolation - An interpolation library for Arduino. -* Author: Jose Gama 2015 - -* -* This library is free software; you can redistribute it -* and/or modify it under the terms of the GNU Lesser -* General Public License as published by the Free Software -* Foundation; either version 3 of the License, or (at -* your option) any later version. -* -* This library is distributed in the hope that it will -* be useful, but WITHOUT ANY WARRANTY; without even the -* implied warranty of MERCHANTABILITY or FITNESS FOR A -* PARTICULAR PURPOSE. See the GNU Lesser General Public -* License for more details. -* -* You should have received a copy of the GNU Lesser -* General Public License along with this library; if not, -* write to the Free Software Foundation, Inc., -* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -* -*/ - -/* - * From: https://github.com/tuxcell/interpolationArduino - * replaced all doubles by float (wirtz@parasitstudio.de) - */ - -#include "interpolation.h" - -interpolation::interpolation(void) { - _valInterp = 0; - _lenXY = 0; -} -interpolation::interpolation( float x[], float y[], int lenXY){ - _x = x;_y = y;_lenXY = lenXY; - _valInterp = 0; -} -interpolation::interpolation( float x[], float y[], int lenXY, float valInterp){ - _x = x;_y = y;_lenXY = lenXY; - _valInterp = valInterp; -} - -void interpolation::valueI( float valInterp ) { - _valInterp = valInterp; -} -void interpolation::valuelenXY( int lenXY ) { - _lenXY = lenXY; -} -void interpolation::valueX( float x[]) { - _x = x; -} -void interpolation::valueY( float y[]) { - _y = y; -} -void interpolation::valueXM( float XM[]) { - _XM = XM; -} -void interpolation::valueZ( float Z[]) { - _Z = Z; -} -float interpolation::LinearInterpolate() {return(LinearInterp( _x, _y, _lenXY, _valInterp));} -float interpolation::CosineInterpolate() {return(CosineInterp( _x, _y, _lenXY, _valInterp));} -float interpolation::CubicInterpolate() {return(CubicInterp( _x, _y, _lenXY, _valInterp));} -float interpolation::LagrangeInterpolate() {return(LagrangeInterp( _x, _y, _lenXY, _valInterp));} -float interpolation::QuadraticInterpolate() {return(QuadraticInterp( _x, _y, _lenXY, _valInterp));} -float interpolation::AkimaInterpolate() {return(AkimaInterp( _x, _y, _XM, _Z, _lenXY, _valInterp));} - - -float interpolation::LinearInterp( float* x, float* y, int n, float p ) -{ - //http://paulbourke.net/miscellaneous/interpolation/ - int i; - float mu; - for( i = 0; i < n-1; i++ ) - { - if (( x[i] <= p && x[i+1] >= p )||( x[i] >= p && x[i+1] <= p )) - { - mu=(p - x[i])/(x[i] - x[i+1]); - if (mu<0) mu=-mu; - return(y[i]*(1-mu)+y[i+1]*mu); - } - } - return 0; // Not in Range -} - -float interpolation::CosineInterp (float* x, float* y, int n, float p ) -{ - int i; - float mu, mu2; - for( i = 0; i < n-1; i++ ) - { - if (( x[i] <= p && x[i+1] >= p )||( x[i] >= p && x[i+1] <= p )) - { - mu=(p - x[i])/(x[i] - x[i+1]); - if (mu<0) mu=-mu; - mu2 = (1.0-cos(3.1415926535897*mu))/2.0; - return(y[i]*(1.0-mu2)+y[i+1]*mu2); - } - } - return 0; // Not in Range -} - -float interpolation::CubicInterp(float* x, float* y, int n, float p ) -{ - int i; - float a0,a1,a2,a3,mu, mu2; - for( i = 0; i < n-1; i++ ) - { - if (( x[i] <= p && x[i+1] >= p )||( x[i] >= p && x[i+1] <= p )) - { - mu=(p - x[i])/(x[i] - x[i+1]); - if (mu<0) mu=-mu; - mu2 = mu*mu; - a0 = y[i+2] - y[i+1] - y[i-1] + y[i]; - a1 = y[i-1] - y[i] - a0; - a2 = y[i+1] - y[i-1]; - a3 = y[i]; - return(a0*mu*mu2+a1*mu2+a2*mu+a3); - } - } - return 0; // Not in Range -} - -float interpolation::LagrangeInterp( float* x, float* y, int n, float p ) -{ - //http://www.dailyfreecode.com/code/lagranges-interpolation-method-finding-2376.aspx - int i, j, k; - float t, r=0; - for(i=0;i= p )||( x[i] >= p && x[i+1] <= p )) - { - if (i<(n-3)) xi2=x[i+2]; else xi2=0; - k = y[i]*(p - x[i+1])*(p - xi2)/((x[i] - x[i+1])*(x[i] - xi2)); - k += y[i+1]*(p - x[i])*(p - xi2)/((x[i+1] - x[i])*(x[i+1] - xi2)); - k += y[i+2]*(p - x[i])*(p - x[i+1])/((xi2 - x[i])*(xi2 - x[i+1])); - return(k); - } - } - return 0; // Not in Range -} - -float interpolation::AkimaInterp( float* x, float* y, float* XM, float* Z, int n, float p ) { - //http://jean-pierre.moreau.pagesperso-orange.fr/Cplus/akima_cpp.txt - int i; - float a,b,r; - //special case p=0 - if (p==0.0) { - return(0); - } - //Check to see if interpolation point is correct - if (p=x[n-3]) { - return(-330); - } - x[0]=2.0*x[1]-x[2]; - //Calculate Akima coefficients, a and b - for (i=1; ix[i]) i++; - i--; - - //Begin interpolation - b=x[i+1]-x[i]; - a=p-x[i]; - r=y[i]+Z[i]*a+(3.0*XM[i+2]-2.0*Z[i]-Z[i+1])*a*a/b; - r=r+(Z[i]+Z[i+1]-2.0*XM[i+2])*a*a*a/(b*b); - return(r); -} diff --git a/old/interpolation.h b/old/interpolation.h deleted file mode 100644 index d07e075..0000000 --- a/old/interpolation.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -* interpolation.h -* -* interpolation - An interpolation library for Arduino. -* Author: Jose Gama 2015 - -* -* This library is free software; you can redistribute it -* and/or modify it under the terms of the GNU Lesser -* General Public License as published by the Free Software -* Foundation; either version 3 of the License, or (at -* your option) any later version. -* -* This library is distributed in the hope that it will -* be useful, but WITHOUT ANY WARRANTY; without even the -* implied warranty of MERCHANTABILITY or FITNESS FOR A -* PARTICULAR PURPOSE. See the GNU Lesser General Public -* License for more details. -* -* You should have received a copy of the GNU Lesser -* General Public License along with this library; if not, -* write to the Free Software Foundation, Inc., -* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -* -*/ - -/* - * From: https://github.com/tuxcell/interpolationArduino - * replaced all doubles by float (wirtz@parasitstudio.de) - */ - -#ifndef interpolation_h -#define interpolation_h - -#if defined(ARDUINO) && ARDUINO >= 100 - #include -#else - #include -#endif - -class interpolation -{ - public: - // constructor - interpolation( void ); - interpolation( float x[], float y[], int lenXY); - interpolation( float x[], float y[], int lenXY, float valInterp); - - void valueI( float valInterp ); - void valuelenXY( int lenXY ); - void valueX( float x[]); - void valueY( float y[]); - void valueXM( float XM[]); - void valueZ( float Z[]); - float LinearInterpolate(); - float CosineInterpolate(); - float CubicInterpolate(); - float LagrangeInterpolate(); - float QuadraticInterpolate(); - float AkimaInterpolate(); - - private: - float* _x; - float* _y; - float* _XM; - float* _Z; - int _lenXY; - float _valInterp; - - float LinearInterp( float x[], float y[], int n, float p ); - float CosineInterp( float x[], float y[], int n, float p ); - float CubicInterp( float x[], float y[], int n, float p ); - float LagrangeInterp( float x[], float y[], int n, float p ); - float QuadraticInterp( float x[], float y[], int n, float p ); - float AkimaInterp( float x[], float y[], float XM[], float Z[], int n, float p ); - -}; - -#endif diff --git a/spline.cpp b/spline.cpp index 4e44c05..47e1599 100644 --- a/spline.cpp +++ b/spline.cpp @@ -8,14 +8,14 @@ Spline::Spline(void) { Spline::Spline( float x[], float y[], int numPoints, int degree ) { - setPoints(x,y,numPoints); + setPoints(x, y, numPoints); setDegree(degree); _prev_point = 0; } Spline::Spline( float x[], float y[], float m[], int numPoints ) { - setPoints(x,y,m,numPoints); + setPoints(x, y, m, numPoints); setDegree(Hermite); _prev_point = 0; } @@ -33,78 +33,88 @@ void Spline::setPoints( float x[], float y[], float m[], int numPoints ) { _length = numPoints; } -void Spline::setDegree( int degree ){ +void Spline::setDegree( int degree ) { _degree = degree; } float Spline::value( float x ) { - if( _x[0] > x ) { - return _y[0]; + if ( _x[0] > x ) { + return _y[0]; } - else if ( _x[_length-1] < x ) { - return _y[_length-1]; + else if ( _x[_length - 1] < x ) { + return _y[_length - 1]; } else { - for(int i = 0; i < _length; i++ ) + for (int i = 0; i < _length; i++ ) { int index = ( i + _prev_point ) % _length; - - if( _x[index] == x ) { + + if ( _x[index] == x ) { _prev_point = index; return _y[index]; - } else if( (_x[index] < x) && (x < _x[index+1]) ) { + } else if ( (_x[index] < x) && (x < _x[index + 1]) ) { _prev_point = index; return calc( x, index ); } - } + } } + return (0.0); } float Spline::calc( float x, int i ) { - switch( _degree ) { + switch ( _degree ) { case 0: return _y[i]; case 1: - if( _x[i] == _x[i+1] ) { + if ( _x[i] == _x[i + 1] ) { // Avoids division by 0 return _y[i]; } else { - return _y[i] + (_y[i+1] - _y[i]) * ( x - _x[i]) / ( _x[i+1] - _x[i] ); + return _y[i] + (_y[i + 1] - _y[i]) * ( x - _x[i]) / ( _x[i + 1] - _x[i] ); } case Hermite: - return hermite( ((x-_x[i]) / (_x[i+1]-_x[i])), _y[i], _y[i+1], _m[i], _m[i+1], _x[i], _x[i+1] ); + return hermite( ((x - _x[i]) / (_x[i + 1] - _x[i])), _y[i], _y[i + 1], _m[i], _m[i + 1], _x[i], _x[i + 1] ); case Catmull: - if( i == 0 ) { + if ( i == 0 ) { // x prior to spline start - first point used to determine tangent return _y[1]; - } else if( i == _length-2 ) { + } else if ( i == _length - 2 ) { // x after spline end - last point used to determine tangent - return _y[_length-2]; + return _y[_length - 2]; } else { - float t = (x-_x[i]) / (_x[i+1]-_x[i]); - float m0 = (i==0 ? 0 : catmull_tangent(i) ); - float m1 = (i==_length-1 ? 0 : catmull_tangent(i+1) ); - return hermite( t, _y[i], _y[i+1], m0, m1, _x[i], _x[i+1]); + float t = (x - _x[i]) / (_x[i + 1] - _x[i]); + float m0 = (i == 0 ? 0 : catmull_tangent(i) ); + float m1 = (i == _length - 1 ? 0 : catmull_tangent(i + 1) ); + return hermite( t, _y[i], _y[i + 1], m0, m1, _x[i], _x[i + 1]); } } + return (0.0); } float Spline::hermite( float t, float p0, float p1, float m0, float m1, float x0, float x1 ) { - return (hermite_00(t)*p0) + (hermite_10(t)*(x1-x0)*m0) + (hermite_01(t)*p1) + (hermite_11(t)*(x1-x0)*m1); + return (hermite_00(t) * p0) + (hermite_10(t) * (x1 - x0) * m0) + (hermite_01(t) * p1) + (hermite_11(t) * (x1 - x0) * m1); +} +float Spline::hermite_00( float t ) { + return (2 * pow(t, 3)) - (3 * pow(t, 2)) + 1; +} +float Spline::hermite_10( float t ) { + return pow(t, 3) - (2 * pow(t, 2)) + t; +} +float Spline::hermite_01( float t ) { + return (3 * pow(t, 2)) - (2 * pow(t, 3)); +} +float Spline::hermite_11( float t ) { + return pow(t, 3) - pow(t, 2); } -float Spline::hermite_00( float t ) { return (2*pow(t,3)) - (3*pow(t,2)) + 1;} -float Spline::hermite_10( float t ) { return pow(t,3) - (2*pow(t,2)) + t; } -float Spline::hermite_01( float t ) { return (3*pow(t,2)) - (2*pow(t,3)); } -float Spline::hermite_11( float t ) { return pow(t,3) - pow(t,2); } -float Spline::catmull_tangent( int i ) -{ - if( _x[i+1] == _x[i-1] ) { +float Spline::catmull_tangent( int i ) +{ + if ( _x[i + 1] == _x[i - 1] ) { // Avoids division by 0 return 0; - } else { - return (_y[i+1] - _y[i-1]) / (_x[i+1] - _x[i-1]); - } + } else { + return (_y[i + 1] - _y[i - 1]) / (_x[i + 1] - _x[i - 1]); + } } diff --git a/spline.h b/spline.h index 8853254..563c742 100644 --- a/spline.h +++ b/spline.h @@ -1,7 +1,7 @@ /* Library for 1-d splines Copyright Ryan Michael - Licensed under the GPLv3 + Licensed under the GPLv3 */ #ifndef spline_h #define spline_h @@ -21,7 +21,7 @@ class Spline void setPoints( float x[], float y[], int numPoints ); void setPoints( float x[], float y[], float m[], int numPoints ); void setDegree( int degree ); - + private: float calc( float, int); float* _x; @@ -30,7 +30,7 @@ class Spline int _degree; int _length; int _prev_point; - + float hermite( float t, float p0, float p1, float m0, float m1, float x0, float x1 ); float hermite_00( float t ); float hermite_10( float t );