Browse Source

Manually merged Pete's pull request: Correct a calculation in flange;remove static class from chorus and flange

https://github.com/PaulStoffregen/Audio/pull/7
dds
PaulStoffregen 11 years ago
parent
commit
8169a8a766
6 changed files with 77 additions and 69 deletions
  1. +7
    -31
      effect_chorus.cpp
  2. +12
    -9
      effect_chorus.h
  3. +40
    -16
      effect_flange.cpp
  4. +11
    -11
      effect_flange.h
  5. +1
    -1
      examples/effect_chorus/effect_chorus.ino
  6. +6
    -1
      examples/effect_flange/effect_flange.ino

+ 7
- 31
effect_chorus.cpp View File



// A u d i o E f f e c t C h o r u s // A u d i o E f f e c t C h o r u s
// Written by Pete (El Supremo) Jan 2014 // Written by Pete (El Supremo) Jan 2014
// 140219 - correct storage class (not static)


// circular addressing indices for left and right channels
short AudioEffectChorus::l_circ_idx;
short AudioEffectChorus::r_circ_idx;

short * AudioEffectChorus::l_delayline = NULL;
short * AudioEffectChorus::r_delayline = NULL;
int AudioEffectChorus::delay_length;
// An initial value of zero indicates passthru
int AudioEffectChorus::num_chorus = 0;


// All three must be valid.
boolean AudioEffectChorus::begin(short *delayline,int d_length,int n_chorus) boolean AudioEffectChorus::begin(short *delayline,int d_length,int n_chorus)
{ {
Serial.print("AudioEffectChorus.begin(Chorus delay line length = "); Serial.print("AudioEffectChorus.begin(Chorus delay line length = ");
Serial.print(n_chorus); Serial.print(n_chorus);
Serial.println(")"); Serial.println(")");


l_delayline = NULL;
r_delayline = NULL;
delay_length = 0;
l_circ_idx = 0;
r_circ_idx = 0;
l_delayline = NULL;
r_delayline = NULL;
delay_length = 0;
l_circ_idx = 0;
r_circ_idx = 0;


if(delayline == NULL) { if(delayline == NULL) {
return(false); return(false);
return(true); return(true);
} }


// This has the same effect as begin(NULL,0);
void AudioEffectChorus::stop(void)
{

}

void AudioEffectChorus::modify(int n_chorus) void AudioEffectChorus::modify(int n_chorus)
{ {
num_chorus = n_chorus; num_chorus = n_chorus;
} }


int iabs(int x)
{
if(x < 0)return(-x);
return(x);
}
//static int d_count = 0;

int last_idx = 0;
//int last_idx = 0;
void AudioEffectChorus::update(void) void AudioEffectChorus::update(void)
{ {
audio_block_t *block; audio_block_t *block;

+ 12
- 9
effect_chorus.h View File



// A u d i o E f f e c t C h o r u s // A u d i o E f f e c t C h o r u s
// Written by Pete (El Supremo) Jan 2014 // Written by Pete (El Supremo) Jan 2014
// 140219 - correct storage class (not static)

#define CHORUS_DELAY_PASSTHRU -1


class AudioEffectChorus : class AudioEffectChorus :
public AudioStream public AudioStream
{ {
public: public:
AudioEffectChorus(void):
AudioStream(2,inputQueueArray) {
}
AudioEffectChorus(void):
AudioStream(2,inputQueueArray), num_chorus(2)
{ }


boolean begin(short *delayline,int delay_length,int n_chorus); boolean begin(short *delayline,int delay_length,int n_chorus);
virtual void update(void); virtual void update(void);
private: private:
audio_block_t *inputQueueArray[2]; audio_block_t *inputQueueArray[2];
static short *l_delayline;
static short *r_delayline;
static short l_circ_idx;
static short r_circ_idx;
static int num_chorus;
static int delay_length;
short *l_delayline;
short *r_delayline;
short l_circ_idx;
short r_circ_idx;
int num_chorus;
int delay_length;
}; };


#endif #endif

+ 40
- 16
effect_flange.cpp View File

// 140207 - fix calculation of delay_rate_incr which is expressed as // 140207 - fix calculation of delay_rate_incr which is expressed as
// a fraction of 2*PI // a fraction of 2*PI
// 140207 - cosmetic fix to begin() // 140207 - cosmetic fix to begin()
// 140219 - correct the calculation of "frac"


// circular addressing indices for left and right channels // circular addressing indices for left and right channels
short AudioEffectFlange::l_circ_idx;
short AudioEffectFlange::r_circ_idx;
//short AudioEffectFlange::l_circ_idx;
//short AudioEffectFlange::r_circ_idx;


short * AudioEffectFlange::l_delayline = NULL;
short * AudioEffectFlange::r_delayline = NULL;
//short * AudioEffectFlange::l_delayline = NULL;
//short * AudioEffectFlange::r_delayline = NULL;


// User-supplied offset for the delayed sample // User-supplied offset for the delayed sample
// but start with passthru // but start with passthru
int AudioEffectFlange::delay_offset_idx = DELAY_PASSTHRU;
int AudioEffectFlange::delay_length;
//int AudioEffectFlange::delay_offset_idx = FLANGE_DELAY_PASSTHRU;
//int AudioEffectFlange::delay_length;


int AudioEffectFlange::delay_depth;
int AudioEffectFlange::delay_rate_incr;
unsigned int AudioEffectFlange::l_delay_rate_index;
unsigned int AudioEffectFlange::r_delay_rate_index;
//int AudioEffectFlange::delay_depth;
//int AudioEffectFlange::delay_rate_incr;
//unsigned int AudioEffectFlange::l_delay_rate_index;
//unsigned int AudioEffectFlange::r_delay_rate_index;
// fails if the user provides unreasonable values but will // fails if the user provides unreasonable values but will
// coerce them and go ahead anyway. e.g. if the delay offset // coerce them and go ahead anyway. e.g. if the delay offset
// is >= CHORUS_DELAY_LENGTH, the code will force it to // is >= CHORUS_DELAY_LENGTH, the code will force it to
if(r_delayline == NULL)return; if(r_delayline == NULL)return;


// do passthru // do passthru
if(delay_offset_idx == DELAY_PASSTHRU) {
if(delay_offset_idx == FLANGE_DELAY_PASSTHRU) {
// Just passthrough // Just passthrough
block = receiveWritable(0); block = receiveWritable(0);
if(block) { if(block) {
if(block) { if(block) {
bp = block->data; bp = block->data;
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) { for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
// increment the index into the circular delay line buffer
l_circ_idx++; l_circ_idx++;
// wrap the index around if necessary
if(l_circ_idx >= delay_length) { if(l_circ_idx >= delay_length) {
l_circ_idx = 0; l_circ_idx = 0;
} }
// store the current sample in the delay line
l_delayline[l_circ_idx] = *bp; l_delayline[l_circ_idx] = *bp;
idx = arm_sin_q15( (q15_t)((l_delay_rate_index >> 16) & 0x7fff));
idx = (idx * delay_depth) >> 15;
// The argument to the arm_sin_q15 function is NOT in radians. It is
// actually, in effect, the fraction remaining after the division
// of radians/(2*PI) which is then expressed as a positive Q15
// fraction in the interval [0 , +1) - this is l_delay_rate_index.
// l_delay_rate_index should probably be called l_delay_rate_phase
// (sorry about that!)
// It is a Q31 positive number of which the high order 16 bits are
// used when calculating the sine. idx will have a value in the
// interval [-1 , +1)
frac = arm_sin_q15( (q15_t)((l_delay_rate_index >> 16) & 0x7fff));
// multiply the sin by the delay depth
idx = (frac * delay_depth) >> 15;
//Serial.println(idx); //Serial.println(idx);
// Calculate the offset into the buffer
idx = l_circ_idx - (delay_offset_idx + idx); idx = l_circ_idx - (delay_offset_idx + idx);
// and adjust idx to point into the circular buffer
if(idx < 0) { if(idx < 0) {
idx += delay_length; idx += delay_length;
} }
idx -= delay_length; idx -= delay_length;
} }


// Here we interpolate between two indices but if the sine was negative
// then we interpolate between idx and idx-1, otherwise the
// interpolation is between idx and idx+1
if(frac < 0) if(frac < 0)
idx1 = idx - 1; idx1 = idx - 1;
else else
idx1 = idx + 1; idx1 = idx + 1;
// adjust idx1 in the circular buffer
if(idx1 < 0) { if(idx1 < 0) {
idx1 += delay_length; idx1 += delay_length;
} }
if(idx1 >= delay_length) { if(idx1 >= delay_length) {
idx1 -= delay_length; idx1 -= delay_length;
} }
// Do the interpolation
frac = (l_delay_rate_index >> 1) &0x7fff; frac = (l_delay_rate_index >> 1) &0x7fff;
frac = (( (int)(l_delayline[idx1] - l_delayline[idx])*frac) >> 15); frac = (( (int)(l_delayline[idx1] - l_delayline[idx])*frac) >> 15);


//frac = 0;
*bp++ = (l_delayline[l_circ_idx] *bp++ = (l_delayline[l_circ_idx]
+ l_delayline[idx] + frac
+ l_delayline[idx] + frac
// + l_delayline[(l_circ_idx + delay_length/2) % delay_length]
)/2; )/2;


l_delay_rate_index += delay_rate_incr; l_delay_rate_index += delay_rate_incr;
r_circ_idx = 0; r_circ_idx = 0;
} }
r_delayline[r_circ_idx] = *bp; r_delayline[r_circ_idx] = *bp;
idx = arm_sin_q15( (q15_t)((r_delay_rate_index >> 16)&0x7fff));
idx = (idx * delay_depth) >> 15;
frac = arm_sin_q15( (q15_t)((r_delay_rate_index >> 16)&0x7fff));
idx = (frac * delay_depth) >> 15;


idx = r_circ_idx - (delay_offset_idx + idx); idx = r_circ_idx - (delay_offset_idx + idx);
if(idx < 0) { if(idx < 0) {
frac = (r_delay_rate_index >> 1) &0x7fff; frac = (r_delay_rate_index >> 1) &0x7fff;
frac = (( (int)(r_delayline[idx1] - r_delayline[idx])*frac) >> 15); frac = (( (int)(r_delayline[idx1] - r_delayline[idx])*frac) >> 15);


//frac = 0;
*bp++ = (r_delayline[r_circ_idx] *bp++ = (r_delayline[r_circ_idx]
+ r_delayline[idx] + frac + r_delayline[idx] + frac
)/2; )/2;

+ 11
- 11
effect_flange.h View File

// A u d i o E f f e c t F l a n g e // A u d i o E f f e c t F l a n g e
// Written by Pete (El Supremo) Jan 2014 // Written by Pete (El Supremo) Jan 2014


#define DELAY_PASSTHRU -1
#define FLANGE_DELAY_PASSTHRU 0


class AudioEffectFlange : class AudioEffectFlange :
public AudioStream public AudioStream
private: private:
audio_block_t *inputQueueArray[2]; audio_block_t *inputQueueArray[2];
static short *l_delayline;
static short *r_delayline;
static int delay_length;
static short l_circ_idx;
static short r_circ_idx;
static int delay_depth;
static int delay_offset_idx;
static int delay_rate_incr;
static unsigned int l_delay_rate_index;
static unsigned int r_delay_rate_index;
short *l_delayline;
short *r_delayline;
int delay_length;
short l_circ_idx;
short r_circ_idx;
int delay_depth;
int delay_offset_idx;
int delay_rate_incr;
unsigned int l_delay_rate_index;
unsigned int r_delay_rate_index;
}; };


#endif #endif

+ 1
- 1
examples/effect_chorus/effect_chorus.ino View File





// number of "voices" in the chorus which INCLUDES the original voice // number of "voices" in the chorus which INCLUDES the original voice
int n_chorus = 3;
int n_chorus = 2;


// <<<<<<<<<<<<<<>>>>>>>>>>>>>>>> // <<<<<<<<<<<<<<>>>>>>>>>>>>>>>>
void setup() { void setup() {

+ 6
- 1
examples/effect_flange/effect_flange.ino View File

#include <Bounce.h> #include <Bounce.h>


// Number of samples in ONE channel // Number of samples in ONE channel
#define FLANGE_DELAY_LENGTH (16*AUDIO_BLOCK_SAMPLES)
#define FLANGE_DELAY_LENGTH (6*AUDIO_BLOCK_SAMPLES)
// Allocate the delay line for left and right channels // Allocate the delay line for left and right channels
// The delayline will hold left and right samples so it // The delayline will hold left and right samples so it
// should be declared to be twice as long as the desired // should be declared to be twice as long as the desired
*/ */


//12 - good with Eric Clapton Unplugged //12 - good with Eric Clapton Unplugged
/*
int s_idx = 3*FLANGE_DELAY_LENGTH/4; int s_idx = 3*FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/8; int s_depth = FLANGE_DELAY_LENGTH/8;
double s_freq = .0625; double s_freq = .0625;
*/
int s_idx = FLANGE_DELAY_LENGTH/4;
int s_depth = FLANGE_DELAY_LENGTH/4;
double s_freq = .5;


void setup() { void setup() {

Loading…
Cancel
Save