Hi everyone,
Finally I got to work SGTL 5000 in way what I want and now Im able to writing own effect codes
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.
Finally I got to work SGTL 5000 in way what I want and now Im able to writing own effect codes
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));
}