Переглянути джерело

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 10 роки тому
джерело
коміт
8169a8a766
6 змінених файлів з 77 додано та 69 видалено
  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 Переглянути файл

@@ -26,19 +26,8 @@

// A u d i o E f f e c t C h o r u s
// 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)
{
Serial.print("AudioEffectChorus.begin(Chorus delay line length = ");
@@ -47,11 +36,11 @@ Serial.print(", n_chorus = ");
Serial.print(n_chorus);
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) {
return(false);
@@ -71,25 +60,12 @@ r_circ_idx = 0;
return(true);
}

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

}

void AudioEffectChorus::modify(int 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)
{
audio_block_t *block;

+ 12
- 9
effect_chorus.h Переглянути файл

@@ -29,14 +29,17 @@

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

#define CHORUS_DELAY_PASSTHRU -1

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

boolean begin(short *delayline,int delay_length,int n_chorus);
virtual void update(void);
@@ -45,12 +48,12 @@ public:
private:
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

+ 40
- 16
effect_flange.cpp Переглянути файл

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

// 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
// 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
// coerce them and go ahead anyway. e.g. if the delay offset
// is >= CHORUS_DELAY_LENGTH, the code will force it to
@@ -132,7 +133,7 @@ void AudioEffectFlange::update(void)
if(r_delayline == NULL)return;

// do passthru
if(delay_offset_idx == DELAY_PASSTHRU) {
if(delay_offset_idx == FLANGE_DELAY_PASSTHRU) {
// Just passthrough
block = receiveWritable(0);
if(block) {
@@ -169,15 +170,30 @@ void AudioEffectFlange::update(void)
if(block) {
bp = block->data;
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
// increment the index into the circular delay line buffer
l_circ_idx++;
// wrap the index around if necessary
if(l_circ_idx >= delay_length) {
l_circ_idx = 0;
}
// store the current sample in the delay line
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);
// Calculate the offset into the buffer
idx = l_circ_idx - (delay_offset_idx + idx);
// and adjust idx to point into the circular buffer
if(idx < 0) {
idx += delay_length;
}
@@ -185,21 +201,28 @@ void AudioEffectFlange::update(void)
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)
idx1 = idx - 1;
else
idx1 = idx + 1;
// adjust idx1 in the circular buffer
if(idx1 < 0) {
idx1 += delay_length;
}
if(idx1 >= delay_length) {
idx1 -= delay_length;
}
// Do the interpolation
frac = (l_delay_rate_index >> 1) &0x7fff;
frac = (( (int)(l_delayline[idx1] - l_delayline[idx])*frac) >> 15);

//frac = 0;
*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;

l_delay_rate_index += delay_rate_incr;
@@ -223,8 +246,8 @@ void AudioEffectFlange::update(void)
r_circ_idx = 0;
}
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);
if(idx < 0) {
@@ -247,6 +270,7 @@ void AudioEffectFlange::update(void)
frac = (r_delay_rate_index >> 1) &0x7fff;
frac = (( (int)(r_delayline[idx1] - r_delayline[idx])*frac) >> 15);

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

+ 11
- 11
effect_flange.h Переглянути файл

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

#define DELAY_PASSTHRU -1
#define FLANGE_DELAY_PASSTHRU 0

class AudioEffectFlange :
public AudioStream
@@ -46,16 +46,16 @@ public:
private:
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

+ 1
- 1
examples/effect_chorus/effect_chorus.ino Переглянути файл

@@ -174,7 +174,7 @@ AudioControlSGTL5000 audioShield;


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

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

+ 6
- 1
examples/effect_flange/effect_flange.ino Переглянути файл

@@ -150,7 +150,7 @@ many blocks you provided with AudioMemory().
#include <Bounce.h>

// 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
// The delayline will hold left and right samples so it
// should be declared to be twice as long as the desired
@@ -221,9 +221,14 @@ double s_freq = .0625;
*/

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

void setup() {

Завантаження…
Відмінити
Зберегти