Arduino-Pedal-Effects/c/New Effects PedalSHIELD UNO/Flanger2/Flanger2.ino

134 lines
4.4 KiB
Arduino
Raw Normal View History

2022-07-18 16:23:07 +00:00
/* Variation based on the flanger from openmusiclabs.com
this program does a flanger effect, and interpolates between samples
for a smoother sound output. a rampwave is used to set the variable
delay. the min and max delay times it swing between is set by MIN
and MAX. these are in samples, divide by 31.25ksps to get ms delay
times. the push buttons determines how much the ramp increments
by each time. this sets the frequency of the delay sweep, which is
min/maxed by B_MIN/B_MAX. In this variant the input signal has been
added to the output.
*/
#include "mult16x8.h"
//defining harware resources.
#define LED 13
#define FOOTSWITCH 12
#define TOGGLE 2
#define PUSHBUTTON_1 A5
#define PUSHBUTTON_2 A4
//defining the output PWM parameters
#define PWM_FREQ 0x00FF // pwm frequency - 31.3KHz
#define PWM_MODE 0 // Fast (1) or Phase Correct (0)
#define PWM_QTY 2 // 2 PWMs in parallel
//defining FX parameters
#define MIN 2 // min delay of ~60us
#define MAX 200 // max delay of ~6ms
#define SIZE MAX+10 // data buffer size - must be more than MAX
int buffer[SIZE]; // create a data buffer
byte dir = 1; // keeps track of up/down counting
unsigned int location = 0; // incoming data buffer pointer
byte button; // button checking timer
byte counter = 4; // button counter (and start value)
unsigned int fractional = 0x00; // fractional sample position
int data_buffer; // temporary data storage to give a 1 sample buffer
int toggle_position=0;
int counter2=0; //buttons timer counter
void setup() {
//setup IO
pinMode(FOOTSWITCH, INPUT_PULLUP);
pinMode(TOGGLE, INPUT_PULLUP);
pinMode(PUSHBUTTON_1, INPUT_PULLUP);
pinMode(PUSHBUTTON_2, INPUT_PULLUP);
pinMode(LED, OUTPUT);
// setup ADC
ADMUX = 0x60; // left adjust, adc0, internal vcc
ADCSRA = 0xe5; // turn on adc, ck/32, auto trigger
ADCSRB = 0x07; // t1 capture for trigger
DIDR0 = 0x01; // turn off digital inputs for adc0
// setup PWM
TCCR1A = (((PWM_QTY - 1) << 5) | 0x80 | (PWM_MODE << 1)); //
TCCR1B = ((PWM_MODE << 3) | 0x11); // ck/1
TIMSK1 = 0x20; // interrupt on capture interrupt
ICR1H = (PWM_FREQ >> 8);
ICR1L = (PWM_FREQ & 0xff);
DDRB |= ((PWM_QTY << 1) | 0x02); // turn on outputs
sei(); // turn on interrupts - not really necessary with arduino
}
void loop() {
if (digitalRead(FOOTSWITCH)) digitalWrite(LED, HIGH);
else digitalWrite(LED, LOW);}
ISR(TIMER1_CAPT_vect) { // all processing happens here
// output the last value calculated
OCR1AL = ((data_buffer + 0x8000) >> 8); // convert to unsigned, send out high byte
OCR1BL = data_buffer; // send out low byte
// get ADC data
byte temp1 = ADCL; // you need to fetch the low byte first
byte temp2 = ADCH; // yes it needs to be done this way
int input = ((temp2 << 8) | temp1) + 0x8000; // make a signed 16b value
//BUTTONS
counter2++; //to save resources, the pushbuttons are checked every 2000 times.
if(counter2==2000)
{
counter2=0;
if (!digitalRead(PUSHBUTTON_1)) {
if (counter > MIN) counter-=1; // if not at min, decrement
}
if (!digitalRead(PUSHBUTTON_2)) {
if (counter < MAX) counter+=1; // if not at max, increment
}
}
// fetch/store data
buffer[location] = input; // store current sample
location++; // go to next sample position
if (location >= SIZE) location = 0; // deal with buffer wrap
int temp = location - (fractional >> 8); // find delayed sample
if (temp < 0) temp += SIZE; // deal with buffer wrap
int output = buffer[temp]+input; // fetch delayed sample
temp -= 1; // find adjacent sample
if (temp < 0) temp += SIZE; // deal with buffer wrap
int output2 = buffer[temp]+input; // get adjacent sample
// interpolate between adjacent samples
int temp4; // create some temp variables
int temp5;
// multiply by distance to fractional position
MultiSU16X8toH16(temp4, output, (0xff - (fractional & 0x00ff)));
MultiSU16X8toH16(temp5, output2, (fractional & 0x00ff));
output = temp4 + temp5; // sum weighted samples
// save value for playback next interrupt
data_buffer = output;
// up or down count as necessary till MIN/MAX is reached
if (dir) {
if ((fractional >> 8) >= MAX) dir = 0;
fractional += counter;
}
else {
if ((fractional >> 8) <= MIN) dir = 1;
fractional -= counter;;
}
}