Realtime pitch shifter, flange, chorus and modulator MULTI FX Project

Diodac

Well-known member
Hi everyone,
Finally I got to work SGTL 5000 in way what I want and now Im able to writing own effect codes :D

Still I have little issues witch my code because I used queues. I know that will be better if I going to create audio objects rather coding like that anyway for now I prefer my way :)
If someone have suggestions how to improve my code and how to fix noise/distortion which occurred occasionally I will be happy and grateful if help me get it better.
The effect is suitable for T4 witch audio shield. There is some initial code witch cool fx, just upload it to your T4 and have good fun!
Effect include modulator, realtime pitch detune, reverb, flanger and chorus.
Code:
/*  Multi Fx by Diodac

    Set effect button on pin 2
    0 = clean
    1 = ring_mod_fx
    2 = pitch_fx
    3 = reverb_fx
    4 = flange_fx
    5 = chorus_fx
    Set level of effect potentiometer on A0
*/
IntervalTimer timer;
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce2.h>
// GUItool: begin automatically generated code
AudioInputI2S            i2s1Record;           //xy=609,170
AudioMixer4              mixer1;         //xy=754,183
AudioPlayQueue           queuePlay;         //xy=876,410
AudioRecordQueue         queueRecord;         //xy=897,184
AudioMixer4              mixer2;         //xy=1032,429
AudioOutputI2S           i2s2Play;           //xy=1216,429
AudioConnection          patchCord1(i2s1Record, 0, mixer1, 0);
AudioConnection          patchCord2(i2s1Record, 1, mixer1, 1);
AudioConnection          patchCord3(mixer1, queueRecord);
AudioConnection          patchCord4(mixer1, 0, mixer2, 1);
AudioConnection          patchCord5(queuePlay, 0, mixer2, 0);
AudioConnection          patchCord6(mixer2, 0, i2s2Play, 0);
AudioConnection          patchCord7(mixer2, 0, i2s2Play, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=923,106
// GUItool: end automatically generated code

#define BUTTON_PIN 2
#define LED_PIN 13
Bounce debouncer = Bounce();

elapsedMillis delayMillis;
elapsedMillis delayControl;

#define MAX_SAMPLES  128
#define MAX_QUEUE_SIZE 8
#define bufferSize 48000
#define bias 512

int16_t FASTRUN buffer[bufferSize];
int16_t DMAMEM bufferIn[MAX_SAMPLES * MAX_QUEUE_SIZE];
int16_t DMAMEM bufferOut[MAX_SAMPLES * MAX_QUEUE_SIZE];
int32_t record_offset = 0, play_offset = 0;
int16_t audioDataInput = 0, audioDataOutput = 0;
static unsigned long pointer = 0;
float volumeControl = 0;
volatile int level = 0;
byte switchEffect = 0;

//Oscillators
#define points 4095
unsigned int FASTRUN modulation[points];

//For Flange & Shifters++++++++++++++++++++
#define MIN 2 //~60us distance
#define MAX 400 //~ 8.5ms distance
#define SIZE 400
#define pitch 11700
byte dir = 1;
unsigned int utime = 0, offset = 0, increment = 0, divider = 0, distance = 0, fractional = 0x00;
int speed = 0, sample = 0, time = 0;
int32_t resultA = 0, resultB = 0, outputA = 0, outputB = 0;

//Modulators & Wobbies++
#define space 350
#define maximum 300
unsigned int wave = bias;
int modulation_in = 0;
int FASTRUN AB[maximum];
int32_t delay_line = 0, line_A = 0, line_B = 0, calculator = 0, fraction = 0;
double down = -0.5, down1 = -0.98, down2 = -0.8;
double up =  0.5, up1 = 0.98, up2 = 0.8;

//Reverb+++++++++++++++
#define D1  4000
#define D2  4000
#define D3  4000
#define D4  4000
#define D5  10000
#define D6  4000
int  DV1 = 100;
int  DV2 = 100;
int  DV3 = 150;
int  DV4 = 200;
int  DV5 = 400;
int  DV6 = 200;
double  x1 = 0.69, x2 = 0.64, x3 = 0.59, x4 = 0.54;
double  y_1 = 0.99 , y_2 = 0.94 , y_3 = 0.89 , y_4 = 0.84;
int FASTRUN X1[D1];
int FASTRUN X2[D2];
int FASTRUN X3[D3];
int FASTRUN X4[D4];
int FASTRUN X5[D5];
int FASTRUN X6[D6];
int32_t  S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0;
long  DC1 = 0, DC2 = 0, DC3 = 0, DC4 = 0, DC5 = 0, DC6 = 1, DC7 = 1, DC8 = 0;

// Multi ++++++++++++++++++++
inline uint32_t M32x16(uint32_t x, uint32_t y) {
  return (uint32_t)(((uint32_t)x) * ((uint32_t)y) >> 16);
}

void setup() {
  Serial.begin(115200);
  AudioMemory(30);
  pinMode(14, INPUT_DISABLE);
  pinMode(15, INPUT_DISABLE);
  pinMode(16, INPUT_DISABLE);
  pinMode(17, INPUT_DISABLE);
  pinMode(22, INPUT_DISABLE);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  debouncer.attach(BUTTON_PIN);
  debouncer.interval(5);


  modulation_generator();

  timer.begin(effect, 22.676);
  timer.priority(64);
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
  sgtl5000_1.micGain(25);
  //sgtl5000_1.lineInLevel(15);
  //sgtl5000_1.lineOutLevel(15);

  mixer1.gain(0, 0.7);
  mixer1.gain(1, 0.7);
  mixer1.gain(2, 0);
  mixer1.gain(3, 0);

  mixer2.gain(0, 1.0); // Fx signal
  mixer2.gain(1, 0);   // Dry signal
  mixer2.gain(2, 0);
  mixer2.gain(3, 0);

  queueRecord.begin();

}

void modulation_generator() {
  for (int i = 0; i < points; i++)
    modulation[i] = (0.99 * cos(((2.0 * PI) / points) * i));
}

void i2s_to_buffer() {
  memcpy(bufferIn + record_offset, queueRecord.readBuffer(), MAX_SAMPLES * 2);
  queueRecord.freeBuffer();
  record_offset += MAX_SAMPLES;
  while (record_offset >= (MAX_SAMPLES * MAX_QUEUE_SIZE))  record_offset = 0;
}

void buffer_to_i2s() {
  memcpy(queuePlay.getBuffer(), bufferOut + play_offset , MAX_SAMPLES * 2);
  queuePlay.playBuffer();
  play_offset += MAX_SAMPLES;
  while (play_offset >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) play_offset = 0;
}

void loop() {
  while (delayControl >= 50) {
    delayControl = 0;
    volumeControl = map(analogRead(A1), 0, 1023, 127, 1023);
    volumeControl = volumeControl / 1023.0;
    sgtl5000_1.volume(volumeControl);
  }

  if (digitalRead(BUTTON_PIN) == LOW) {
    digitalWrite(LED_PIN, HIGH );
  } else digitalWrite(LED_PIN, LOW );
  delay(5);
}

void effect() {
  while (queueRecord.available() >= 2) i2s_to_buffer(), buffer_to_i2s();
  while (delayMillis >= 5) {
    delayMillis = 0;
    level = map(analogRead(A0), 0, 1023, 0, 1023);
  }
  debouncer.update();
  if (debouncer.rose()) {
    switchEffect = switchEffect + 1.0;
  }

  if (switchEffect >= 6) switchEffect = 0;

  switch (switchEffect) {
    case 0:
      clean();
      break;
    case 1:
      ring_mod_fx();
      break;
    case 2:
      pitch_fx();
      break;
    case 3:
      reverb_fx();
      break;
    case 4:
      flange_fx();
      break;
    case 5:
      chorus_fx();
      break;
  }
}

void clean() {
  pointer++;
  audioDataInput = bufferIn[pointer];
  bufferOut[pointer] = audioDataInput >> 1;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;
}

void ring_mod_fx() {
  pointer++;
  audioDataInput = bufferIn[pointer] >> 1;
  bufferOut[pointer] = audioDataOutput;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;
  time = map(level, 0, 1023, 330, 1);
  static long buffIn = bufferSize, buffOut = bufferSize - time;
  buffer[buffIn] = audioDataInput;
  buffIn++;
  if (buffIn >= space) buffIn = 0;
  buffOut = buffIn + offset;
  if (buffOut >= space) buffOut -= space;
  audioDataOutput = buffer[buffOut];
  if (dir) {
    if (offset >= (space - (unsigned int)time)) {
      dir = 0;
      offset--;
    }
    else offset++;
  }
  else {
    if (offset <= 4) {
      dir = 1;
      offset--;
    }
    else offset -= 1;
  }
}

void pitch_fx() {
  static unsigned int locationIn = SIZE, locationOut = SIZE - fractional;
  pointer++;
  audioDataInput = bufferIn[pointer] >> 1;
  bufferOut[pointer] = audioDataOutput;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;

  buffer[locationIn] = audioDataInput;
  locationIn++;
  if (locationIn >= SIZE) locationIn = 0;
  locationOut = locationIn + offset;
  if (locationOut >= SIZE) locationOut -= SIZE;
  outputA = buffer[locationOut];
  locationOut += (SIZE >> 1);
  if (locationOut >= SIZE) locationOut -= SIZE;
  outputB = buffer[locationOut];
  if (offset > (SIZE >> 1)) distance = SIZE - offset;
  else distance = offset;
  resultA = M32x16(outputA, (distance << 7));
  resultB = M32x16(outputB, (((SIZE >> 1) - distance) << 7));
  audioDataOutput = resultA += resultB;
  if (level > bias) {
    fractional += map(level, 511, 1023, 0, 63);
    if (fractional >= 0x0080) {
      offset += (fractional >> 7);
      fractional &= 0x007f;
    }
    if (offset >= SIZE) offset -= SIZE;
  } else if (level < bias) {
    fractional += map(level, 0, 511, 63, 0);
    if (fractional >= 0x0080) {
      offset -= (fractional >> 7);
      fractional &= 0x007f;
    }
    if (offset >= SIZE) offset += SIZE;
  }
}

void reverb_fx() {
  pointer++;
  audioDataInput = bufferIn[pointer] >> 1;
  bufferOut[pointer] = audioDataOutput;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;

  DV1 = map(level << 2, 0, 4095, 100, 4000);
  DV2 = map(level << 2, 0, 4095, 100, 4000);
  DV3 = map(level << 2, 0, 4095, 150, 4000);
  DV4 = map(level << 2, 0, 4095, 200, 4000);
  DV5 = map(level << 2, 0, 4095, 400, 10000);
  DV6 = map(level << 2, 0, 4095, 200, 4000);

  X1[DC1] = (audioDataInput + x1 * X1[DC1] / 1.2);
  X2[DC2] = (audioDataInput + x2 * X2[DC2] / 1.4);
  X3[DC3] = (audioDataInput * X3[DC3] / 1.6);
  X4[DC4] = (audioDataInput * X4[DC4] / 1.8);

  S1 =  y_1 * X1[DC1];
  S2 =  y_2 * X2[DC2];
  S3 =  y_3 * X3[DC3];
  S4 =  y_4 * X4[DC4];

  DC1++; if (DC1 >= DV1) DC1 = 0;
  DC2++; if (DC2 >= DV2) DC2 = 0;
  DC3++; if (DC3 >= DV3) DC3 = 0;
  DC4++; if (DC4 >= DV4) DC4 = 0;

  S5 = (S1 + S2 + S3 + S4) / 4;
  X5[DC7] = (S5 + x3 * X5[DC5]);
  S6 = -x3 * X5[DC7] + X5[DC5];
  DC5++; if (DC5 >= DV5) DC5 = 0;
  DC7++; if (DC7 >= D5) DC7 = 0;
  X6[DC8] = (S6 + x4 * X6[DC6]);
  S7 = (int32_t)(-x4 * X6[DC8] + X6[DC6]);
  DC6++; if (DC6 >= DV6) DC6 = 0;
  DC8++; if (DC8 >= D6) DC8 = 0;
  audioDataOutput = S7;
}

void flange_fx() {
  static int locationIn = SIZE, locationOut = SIZE - fractional;
  pointer++;
  audioDataInput = bufferIn[pointer] >> 1;
  bufferOut[pointer] = audioDataOutput;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;

  buffer[locationIn] = audioDataInput;
  locationIn++;
  if (locationIn >= SIZE) locationIn = 0;
  locationOut = locationIn - (fractional >> 8);
  if (locationOut < 0) locationOut += SIZE;
  outputA = buffer[locationOut] + audioDataInput;
  locationOut -= 1;
  if (locationOut < 0) locationOut += SIZE;
  outputB = buffer[locationOut] + audioDataInput;
  resultA = M32x16(outputA, ((0xff - (fractional & 0x00ff)) << 7));
  resultB = M32x16(outputB, ((fractional & 0x00ff) << 7));
  audioDataOutput = (resultA += resultB);
  int shift = level >> 6;
  if (shift >= 11) shift = 11;
  if (dir) {
    if ((fractional >> 8) >= MAX) dir = 0;
    fractional += (1 + shift);
  }
  else {
    if ((fractional >> 8) <= MIN) dir = 1;
    fractional -= (1 + shift);
  }
}

void chorus_fx() {
  pointer++;
  audioDataInput = bufferIn[pointer] >> 1;
  bufferOut[pointer] = audioDataOutput;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;

  modulation_in = (2 + (level >> 3));
  delay_line = modulation_in / 2;
  for (int index = 0; index <= modulation_in; index++)
    AB[modulation_in + 1 - index] = AB[modulation_in - index];
  AB[0] = up * audioDataInput + down * AB[delay_line];
  line_A = delay_line - delay_line * modulation[calculator * 2];
  line_B =  int32_t(line_A);
  fraction = line_A - line_B;
  if (fraction == 0) fraction = 0.01;
  if (fraction == 1) fraction = 0.99;
  calculator++;
  if (calculator * 2 >= points) calculator = 0;
  audioDataOutput = (int32_t)(AB[line_B + 1] * fraction + AB[line_B] * (1 - fraction));
}
 
I little bit improve my code and now it working better. But still comes strange artifactual noise in constant time interval approximately every 7 minutes. it is really weird and I can't find the problem. Also schroeder reverb need small improvement. Pitch shifter, chorus and flange working pretty nice :D
Hopefully, Paul maybe you help me find mistake in my code, the incoming noise is a big problem.
Code:
/*  Multi Fx by Diodac

    Set effect button on pin 2
    0 = clean
    1 = ring_mod_fx
    2 = pitch_fx
    3 = reverb_fx
    4 = flange_fx
    5 = chorus_fx
    Set level of effect potentiometer on A0
    Set level of volume potentiometer on A1
    Set level of dry/wet potentiometer on A2
*/
IntervalTimer timer;
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce2.h>
// GUItool: begin automatically generated code
AudioInputI2S            i2s1Record;           //xy=609,170
AudioMixer4              mixer1;         //xy=754,183
AudioPlayQueue           queuePlay;         //xy=876,410
AudioRecordQueue         queueRecord;         //xy=897,184
AudioMixer4              mixer2;         //xy=1032,429
AudioOutputI2S           i2s2Play;           //xy=1216,429
AudioConnection          patchCord1(i2s1Record, 0, mixer1, 0);
AudioConnection          patchCord2(i2s1Record, 1, mixer1, 1);
AudioConnection          patchCord3(mixer1, queueRecord);
AudioConnection          patchCord4(mixer1, 0, mixer2, 1);
AudioConnection          patchCord5(queuePlay, 0, mixer2, 0);
AudioConnection          patchCord6(mixer2, 0, i2s2Play, 0);
AudioConnection          patchCord7(mixer2, 0, i2s2Play, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=923,106
// GUItool: end automatically generated code

#define BUTTON_PIN 2
#define LED_PIN 13
Bounce change_fx = Bounce();

elapsedMillis delayMillis;
elapsedMillis delayControl;

#define MAX_SAMPLES 128
#define MAX_QUEUE_SIZE 8
#define bufferSize 48000
#define bias 512

short FASTRUN buffer[bufferSize];
short FASTRUN bufferIn[MAX_SAMPLES * MAX_QUEUE_SIZE];
short FASTRUN bufferOut[MAX_SAMPLES * MAX_QUEUE_SIZE];
int16_t queue_offset = 0, pointer = 0;
volatile float volumeControl = 0, wet = 0, dry = 0;
volatile int level = 0;
byte switchEffect = 0;

//Oscillators
#define points 16383
unsigned int FASTRUN modulation[points];

//For Flange & Shifters++++++++++++++++++++
#define MIN 2 //~60us distance
#define MAX 400 //~ 8.5ms distance
#define SIZE 400
#define pitch 11700
byte dir = 1;
unsigned int utime = 0, offset = 0, increment = 0, divider = 0, distance = 0, fractional = 0x00;
int speed = 0, sample = 0, time = 0;
int32_t resultA = 0, resultB = 0, outputA = 0, outputB = 0;

//Modulators & Wobbies+++++++++++++++++++++++++++
#define space 350
#define maximum 300
unsigned int wave = bias;
int modulation_in = 0;
int FASTRUN AB[maximum];
int32_t delay_line = 0, line_A = 0, line_B = 0, calculator = 0, fraction = 0;
double down = -0.6, down1 = -0.98, down2 = -0.8;
double up =  0.6, up1 = 0.98, up2 = 0.8;

//Reverb+++++++++++++++++++++++++++++
#define D1  4000
#define D2  4000
#define D3  4000
#define D4  4000
#define D5  10000
#define D6  4000
int  DV1 = 100;
int  DV2 = 100;
int  DV3 = 150;
int  DV4 = 200;
int  DV5 = 400;
int  DV6 = 200;
double  x1 = 0.69, x2 = 0.64, x3 = 0.59, x4 = 0.54;
double  y_1 = 0.99 , y_2 = 0.94 , y_3 = 0.89 , y_4 = 0.84;
short FASTRUN X1[D1];
short FASTRUN X2[D2];
short FASTRUN X3[D3];
short FASTRUN X4[D4];
short FASTRUN X5[D5];
short FASTRUN X6[D6];
double  S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0;
int32_t  DC1 = 0, DC2 = 0, DC3 = 0, DC4 = 0, DC5 = 0, DC6 = 1, DC7 = 1, DC8 = 0;

// Multi ++++++++++++++++++++
inline uint32_t M32x16(uint32_t x, uint32_t y) {
  return (uint32_t)(((uint32_t)x) * ((uint32_t)y) >> 16);
}

void setup() {
  Serial.begin(115200);
  AudioMemory(32);
  pinMode(14, INPUT_DISABLE);
  pinMode(15, INPUT_DISABLE);
  pinMode(16, INPUT_DISABLE);
  pinMode(17, INPUT_DISABLE);
  pinMode(22, INPUT_DISABLE);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(LED_PIN, OUTPUT);
  change_fx.attach(BUTTON_PIN);
  change_fx.interval(15);

  modulation_oscillator();

  timer.begin(effect, 22.676);
  timer.priority(128);
  sgtl5000_1.enable();
  sgtl5000_1.volume(1.0);
  sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
  sgtl5000_1.micGain(25);
  //sgtl5000_1.lineInLevel(15);
  //sgtl5000_1.lineOutLevel(15);

  mixer1.gain(2, 0);
  mixer1.gain(3, 0);
  mixer2.gain(2, 0);
  mixer2.gain(3, 0);

  queuePlay.setBehaviour(AudioPlayQueue::NON_STALLING);
  queuePlay.setMaxBuffers(8);
  queueRecord.begin();

}

void modulation_oscillator() {
  for (int i = 0; i < points; i++)
    modulation[i] = (0.99 * cos(((2.0 * PI) / points) * i));
}

void i2s() {
  memcpy(&bufferIn[queue_offset], queueRecord.readBuffer(), 256);
  queueRecord.freeBuffer();
  int16_t *output = queuePlay.getBuffer();
  memcpy(output, &bufferOut[queue_offset] , 256);
  queue_offset += MAX_SAMPLES;
  while (queue_offset >= (MAX_SAMPLES * MAX_QUEUE_SIZE))  queue_offset = 0;
  queuePlay.playBuffer();
}

void loop() {
  while (delayControl >= 50) {
    delayControl = 0;
    mixer1.gain(0, volumeControl);
    mixer1.gain(1, volumeControl);
    mixer2.gain(0, wet);
    mixer2.gain(1, dry);
  }

  if (digitalRead(BUTTON_PIN) == LOW) {
    digitalWrite(LED_PIN, HIGH );
  } else digitalWrite(LED_PIN, LOW );
}

void effect() {
  while (queueRecord.available()) i2s();
  while (delayMillis >= 50) {
    delayMillis = 0;
    level = map(analogRead(A0), 0, 1023, 0, 1023);
    volumeControl = map(analogRead(A1), 0, 1023, 0, 1000);
    volumeControl = volumeControl / 1000.0;
    int val = map(analogRead(A2), 0, 1023, 0, 1000);
    wet = (float)val;
    wet = wet / 1000.0;
    dry = (float)map(val, 0, 1000, 10, 0);
    dry = dry / 10.0;

    change_fx.update();
    if (change_fx.rose()) {
      switchEffect = switchEffect + 1.0;
    }
  }

  if (switchEffect >= 6) switchEffect = 0;

  switch (switchEffect) {
    case 0:
      clean();
      break;
    case 1:
      ring_mod_fx();
      break;
    case 2:
      pitch_fx();
      break;
    case 3:
      reverb_fx();
      break;
    case 4:
      flange_fx();
      break;
    case 5:
      chorus_fx();
      break;
  }
}

void clean() {
  pointer++;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;
  bufferOut[pointer] = bufferIn[pointer];

}

void ring_mod_fx() {
  static long buffIn = bufferSize, buffOut = bufferSize - time;

  pointer++;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;
  time = map(level, 0, 1023, 330, 1);
  buffer[buffIn] = bufferIn[pointer];
  buffIn++;
  if (buffIn >= space) buffIn = 0;
  buffOut = buffIn + offset;
  if (buffOut >= space) buffOut -= space;
  bufferOut[pointer] = buffer[buffOut];
  if (dir) {
    if (offset >= (space - (unsigned int)time)) {
      dir = 0;
      offset--;
    }
    else offset++;
  }
  else {
    if (offset <= 4) {
      dir = 1;
      offset--;
    }
    else offset -= 1;
  }
}

void pitch_fx() {
  static unsigned int locationIn = SIZE, locationOut = SIZE - fractional;

  pointer++;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;
  buffer[locationIn] = bufferIn[pointer];
  locationIn++;
  if (locationIn >= SIZE) locationIn = 0;
  locationOut = locationIn + offset;
  if (locationOut >= SIZE) locationOut -= SIZE;
  outputA = buffer[locationOut];
  locationOut += (SIZE >> 1);
  if (locationOut >= SIZE) locationOut -= SIZE;
  outputB = buffer[locationOut];
  if (offset > (SIZE >> 1)) distance = SIZE - offset;
  else distance = offset;
  resultA = M32x16(outputA, (distance << 7));
  resultB = M32x16(outputB, (((SIZE >> 1) - distance) << 7));
  bufferOut[pointer] = resultA += resultB;
  if (level > bias) {
    fractional += map(level, 511, 1023, 0, 63);
    if (fractional >= 0x0080) {
      offset += (fractional >> 7);
      fractional &= 0x007f;
    }
    if (offset >= SIZE) offset -= SIZE;
  } else if (level < bias) {
    fractional += map(level, 0, 511, 63, 0);
    if (fractional >= 0x0080) {
      offset -= (fractional >> 7);
      fractional &= 0x007f;
    }
    if (offset >= SIZE) offset += SIZE;
  }
}

void reverb_fx() {
  pointer++;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;

  DV1 = map(level, 0, 1023, 100, 4000);
  DV2 = map(level, 0, 1023, 100, 4000);
  DV3 = map(level, 0, 1023, 150, 4000);
  DV4 = map(level, 0, 1023, 200, 4000);
  DV5 = map(level, 0, 1023, 400, 10000);
  DV6 = map(level, 0, 1023, 200, 4000);

  X1[DC1] = (bufferIn[pointer] + x1 * X1[DC1] / 1.2);
  X2[DC2] = (bufferIn[pointer] + x2 * X2[DC2] / 1.4);
  X3[DC3] = (bufferIn[pointer] * X3[DC3] / 1.6);
  X4[DC4] = (bufferIn[pointer] * X4[DC4] / 1.8);

  S1 =  y_1 * X1[DC1];
  S2 =  y_2 * X2[DC2];
  S3 =  y_3 * X3[DC3];
  S4 =  y_4 * X4[DC4];

  DC1++; if (DC1 >= DV1) DC1 = 0;
  DC2++; if (DC2 >= DV2) DC2 = 0;
  DC3++; if (DC3 >= DV3) DC3 = 0;
  DC4++; if (DC4 >= DV4) DC4 = 0;

  S5 = (S1 + S2 + S3 + S4) / 4;
  X5[DC7] = (S5 + x3 * X5[DC5]);
  S6 = -x3 * X5[DC7] + X5[DC5];
  DC5++; if (DC5 >= DV5) DC5 = 0;
  DC7++; if (DC7 >= D5) DC7 = 0;
  X6[DC8] = (S6 + x4 * X6[DC6]);
  S7 = (-x4 * X6[DC8] + X6[DC6]);
  DC6++; if (DC6 >= DV6) DC6 = 0;
  DC8++; if (DC8 >= D6) DC8 = 0;
  bufferOut[pointer] = (int16_t)S7;
}

void flange_fx() {
  static int locationIn = SIZE, locationOut = SIZE - fractional;

  pointer++;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;
  buffer[locationIn] = bufferIn[pointer];
  locationIn++;
  if (locationIn >= SIZE) locationIn = 0;
  locationOut = locationIn - (fractional >> 8);
  if (locationOut < 0) locationOut += SIZE;
  outputA = buffer[locationOut] + bufferIn[pointer];
  locationOut -= 1;
  if (locationOut < 0) locationOut += SIZE;
  outputB = buffer[locationOut] + bufferIn[pointer];
  resultA = M32x16(outputA, ((0xff - (fractional & 0x00ff)) << 7));
  resultB = M32x16(outputB, ((fractional & 0x00ff) << 7));
  bufferOut[pointer] = (resultA += resultB);
  int shift = level >> 6;
  if (shift >= 11) shift = 11;
  if (dir) {
    if ((fractional >> 8) >= MAX) dir = 0;
    fractional += (1 + shift);
  }
  else {
    if ((fractional >> 8) <= MIN) dir = 1;
    fractional -= (1 + shift);
  }
}

void chorus_fx() {
  pointer++;
  while (pointer >= (MAX_SAMPLES * MAX_QUEUE_SIZE)) pointer = 0;
  modulation_in = (2 + (level >> 3));
  delay_line = modulation_in / 2;
  for (int index = 0; index <= modulation_in; index++)
    AB[modulation_in + 1 - index] = AB[modulation_in - index];
  AB[0] = up * bufferIn[pointer] + down * AB[delay_line];
  line_A = delay_line - delay_line * modulation[calculator * 2];
  line_B =  int32_t(line_A);
  fraction = line_A - line_B;
  if (fraction == 0) fraction = 0.01;
  if (fraction == 1) fraction = 0.99;
  calculator++;
  if (calculator * 2 >= points) calculator = 0;
  bufferOut[pointer] = (int32_t)(AB[line_B + 1] * fraction + AB[line_B] * (1 - fraction));
}
 
Back
Top