Patrick1992
Member
Hi, got an effect to a stage i like and it’s working. I’m trying to use an LFO as found in this example, but removing the oscillator obviously:
I’m trying to implement it in my code to modulate the state variable filter cutoff, however i’m not getting any output currently. I’ve manually ‘patched’ things in so perhaps it’s a mistake there or it’s a problem with how i’m trying to integrate the LFO to my code. In the above code i can sort of see how the LFO works and how it reads the pot values to update speed and depth but i can’t actually figure out what it’s doing with this output.
Anyway, here is where i’m at. I would be extremely grateful for any thoughts or pointers. Apologies if the code is an absolute casserole.
For reference, here is the same code without the LFO which works fine:
Code:
#include <math.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioSynthWaveformDc pitchAmt; //xy=90,133
AudioSynthWaveform LFO; //xy=90,194
AudioSynthWaveformDc filterAmt; //xy=90,255
AudioEffectMultiply multiply; //xy=247,160
AudioEffectMultiply multiply1; //xy=250,233
AudioSynthWaveformModulated oscillator; //xy=396,166
AudioFilterStateVariable filter; //xy=541,224
AudioOutputI2S i2s; //xy=707,208
AudioConnection patchCord1(pitchAmt, 0, multiply, 0);
AudioConnection patchCord2(LFO, 0, multiply, 1);
AudioConnection patchCord3(LFO, 0, multiply1, 0);
AudioConnection patchCord4(filterAmt, 0, multiply1, 1);
AudioConnection patchCord5(multiply, 0, oscillator, 0);
AudioConnection patchCord6(multiply1, 0, filter, 1);
AudioConnection patchCord7(oscillator, 0, filter, 0);
AudioConnection patchCord8(filter, 0, i2s, 0);
AudioConnection patchCord9(filter, 0, i2s, 1);
AudioControlSGTL5000 sgtl5000; //xy=618,140
// GUItool: end automatically generated code
#define PITCH_POT A0
#define CUTOFF_POT A1
#define RATE_POT A2
#define AMOUNT_POT A3
#define LED 3
#define PITCH_FLT_SW 4
int pitch = 220;
int cutoff = 2000;
int rate = 0;
int amount = 0;
bool isPitch = true;
// pitch scales logarithmically
float inputToPitch(int input)
{
int n = map(input, 0, 1023, 21, 108);
return 440 * pow(2, (n - 69) / 12.0);
}
// input is from 0 to 127
void setCutoff(int u)
{
// Use an exponential curve from 50Hz to about 12kHz
float co = 50 * exp(5.481 * u / 127.0);
filter.frequency(co);
filter.octaveControl(log2f(12000.0 / (float)co));
}
void setLFORate(int u)
{
// convert log scale 0 to 127 to a linear rate
// f(1) = 0.5Hz, f(127) = 40Hz
float f = exp(u / 25.0) / 4.0;
LFO.frequency(f);
}
void updateLFO()
{
digitalWrite(LED, isPitch);
pitchAmt.amplitude(isPitch ? amount / 127.0 : 0);
filterAmt.amplitude(isPitch ? 0 : amount / 127.0);
}
void setup()
{
// reserve some memory for the audio functions
AudioMemory(20);
// enable the audio control chip on the Audio Shield
sgtl5000.enable();
sgtl5000.volume(0.5);
// setup the two pins for listening to the pitch and amplitude controls
pinMode(PITCH_POT, INPUT);
pinMode(CUTOFF_POT, INPUT);
pinMode(RATE_POT, INPUT);
pinMode(AMOUNT_POT, INPUT);
// and the switch/LED pins
pinMode(LED, OUTPUT);
pinMode(PITCH_FLT_SW, INPUT_PULLUP);
updateLFO();
// configure and start the oscillator object
oscillator.amplitude(0.5);
oscillator.frequency(pitch);
oscillator.begin(WAVEFORM_SAWTOOTH);
oscillator.frequencyModulation(1);
setLFORate(rate);
LFO.amplitude(1);
LFO.begin(WAVEFORM_TRIANGLE);
}
void loop()
{
static long lastpress = 0;
// are we modulating pitch or filter?
if ((digitalRead(PITCH_FLT_SW) == 0) && (millis() - lastpress > 200)) // switch is on (line pulled low)
{
lastpress = millis();
isPitch = !isPitch;
updateLFO();
}
// read the pitch pot position
int newpitch = analogRead(PITCH_POT);
// has it changed?
if (newpitch != pitch)
{
// update if it has
pitch = newpitch;
oscillator.frequency(inputToPitch(newpitch));
}
// read the cutoff pot position
int newcutoff = analogRead(CUTOFF_POT) >> 3;
// has it changed?
if (newcutoff != cutoff)
{
// update if it has
cutoff = newcutoff;
setCutoff(cutoff);
}
// read the LFO rate pot position
int newrate = analogRead(RATE_POT) >> 3;
// has it changed?
if (newrate != rate)
{
// update if it has
rate = newrate;
setLFORate(rate);
}
// read the amount pot position
int newamount = analogRead(AMOUNT_POT) >> 3;
// has it changed?
if (newamount != amount)
{
// update if it has
amount = newamount;
updateLFO();
}
}
I’m trying to implement it in my code to modulate the state variable filter cutoff, however i’m not getting any output currently. I’ve manually ‘patched’ things in so perhaps it’s a mistake there or it’s a problem with how i’m trying to integrate the LFO to my code. In the above code i can sort of see how the LFO works and how it reads the pot values to update speed and depth but i can’t actually figure out what it’s doing with this output.
Anyway, here is where i’m at. I would be extremely grateful for any thoughts or pointers. Apologies if the code is an absolute casserole.
Code:
#define LED 3
#include <Bounce.h>
#include <ResponsiveAnalogRead.h>
#include <vibrato.h>
#include "effect_delay10tap.h"
#include <math.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
//LFO BITS
AudioSynthWaveform LFO; //xy=90,194
AudioSynthWaveformDc filterAmt; //xy=90,255
AudioEffectMultiply multiply; //xy=250,233
//FX BITS
AudioInputI2S i2s1; //xy=82,344
AudioMixer4 mixer1; //xy=162,96
AudioEffectBitcrusher bitcrusher1; //xy=255,27
AudioEffectDelay10tap delay1; //xy=307,220
AudioAmplifier amp1; //xy=409,29
AudioMixer4 mixer2; //xy=462,224
AudioFilterStateVariable filter1; //xy=535,37
AudioFilterBiquad biquad1;
AudioOutputI2S i2s2; //xy=746,214
AudioEffect_Vibrato vibrato1;
//PATCHING
AudioConnection patchCord1(i2s1, 0, vibrato1, 0);
AudioConnection patchCord2(vibrato1, 0, mixer1, 0);
AudioConnection patchCord3(i2s1, 0, bitcrusher1, 0);
AudioConnection patchCord4(i2s1, 0, mixer2, 1);
AudioConnection patchCord5(mixer1, delay1);
AudioConnection patchCord6(bitcrusher1, amp1);
AudioConnection patchCord7(delay1, 0, mixer1, 1);
AudioConnection patchCord8(delay1, 0, mixer2, 0);
AudioConnection patchCord9(delay1, 1, mixer2, 2);
AudioConnection patchCord10(amp1, biquad1);
AudioConnection patchCord11(biquad1, filter1);
AudioConnection patchCord12(mixer2, 0, i2s2, 0);
AudioConnection patchCord13(filter1, 1, mixer1, 2);
AudioConnection patchCord14(LFO, 0, multiply, 0);
AudioConnection patchCord15(filterAmt, 0, multiply, 1);
AudioConnection patchCord16(multiply, 0, filter1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=767,328
#define RATE_POT A5
#define AMOUNT_POT A6
#define LED 3
#define PITCH_FLT_SW 4
int LFOrate = 0;
int amount = 0;
bool isPitch = true;
void setCutoff(int u)
{
// Use an exponential curve from 50Hz to about 12kHz
float co = 50 * exp(5.481 * u / 127.0);
filter1.frequency(co);
filter1.resonance (5);
filter1.octaveControl(log2f(12000.0 / (float)co));
}
void setLFORate(int u)
{
// convert log scale 0 to 127 to a linear rate
// f(1) = 0.5Hz, f(127) = 40Hz
float f = exp(u / 25.0) / 4.0;
LFO.frequency(f);
}
void updateLFO()
{
digitalWrite(LED, isPitch);
filterAmt.amplitude(isPitch ? 0 : amount / 127.0);
}
// delay line
#define DELAYLINE_MAX_LEN 45159 // number of samples at 44100 samples a second
int16_t delay_line[DELAYLINE_MAX_LEN] = {};
// main timing loop
#define LOOP0_DURATION 20 // interval time in millis
elapsedMillis loop0_timer;
// pot to control delaytime
const int DELAY_TIME_KNOB_PIN = A4; // A12 gain
ResponsiveAnalogRead delayTimeKnob(DELAY_TIME_KNOB_PIN, true);
/*
Bounce footswitch = Bounce(0, 50); // debounce the footswitch
Bounce D1 = Bounce(1, 50); // debounce the toggle switch
Bounce D2 = Bounce(2, 50); // " " " " " " " " "
// this section includes the function to check the toggle position
bool right;
bool middle;
bool left;
void checkToggle () { // this is our function to check toggle position...
D1.update(); D2.update(); // check digital inputs connected to toggle (can delete I think)
if (digitalRead(1) && !digitalRead(2)) {
right = 1; // toggle is right
middle = 0;
left = 0;
}
if (digitalRead(1) && digitalRead(2)) {
right = 0; // toggle is in the middle
middle = 1;
left = 0;
}
if (!digitalRead(1) && digitalRead(2)) {
right = 0; // toggle is left
middle = 0;
left = 1;
}
}
*/
byte bitdepth = 16; // used to set bit depth
int samplerate = 44100; // used to set sample rate
float mix; // clean/delay mix
float mix1; // clean/delay mix
float feedback; // delay feedback
int bandpass; //bandpass cutoff frequency
int delaytime;
void setup() {
pinMode(RATE_POT, INPUT);
pinMode(AMOUNT_POT, INPUT);
pinMode(LED, OUTPUT);
pinMode(PITCH_FLT_SW, INPUT_PULLUP);
updateLFO();
setLFORate(LFOrate);
LFO.amplitude(1);
LFO.begin(WAVEFORM_TRIANGLE);
AudioMemory(400); // the "40" represents how much internal memory (in the Teensy, not the external RAM chip) is allotted for audio recording. It is measured in sample blocks, each providing 2.9ms of audio.
sgtl5000_1.enable(); // this turns on the SGTL5000, which is the audio codec on the audio board
sgtl5000_1.volume(1); // this sets the output volume (it can be between 0 and 1)
sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); // selects the audio input, we always use Line In
// analogReadResolution(10); // configure the pots to give 12 bit readings
pinMode(0, INPUT_PULLUP); // internal pull-up resistor for footswitch
pinMode(1, INPUT_PULLUP); // internal pull-up resistor for toggle
pinMode(2, INPUT_PULLUP); // internal pull-up resistor for toggle
pinMode(3, OUTPUT); // pin 3 (the LED) is an output;
Serial.begin(115200); // initiate the serial monitor. USB is always 12 Mbit/sec
sgtl5000_1.audioPostProcessorEnable();
//analogReadAveraging(10);
// start up the effect and pass it an array to store the samples
delay1.begin(delay_line, DELAYLINE_MAX_LEN);
}
float VibeRate = 1;
float VibeDepth = 10;
void loop() {
static long lastpress = 0;
// are we modulating pitch or filter?
if ((digitalRead(PITCH_FLT_SW) == 0) && (millis() - lastpress > 200)) // switch is on (line pulled low)
{
lastpress = millis();
isPitch = !isPitch;
updateLFO();
}
// read the LFO rate pot position
int newrate = analogRead(RATE_POT) >> 3;
// has it changed?
if (newrate != LFOrate)
{
// update if it has
LFOrate = newrate;
setLFORate(LFOrate);
}
// read the LFO amount pot position
int newamount = analogRead(AMOUNT_POT) >> 3;
// has it changed?
if (newamount != amount)
{
// update if it has
amount = newamount;
updateLFO();
}
vibrato1.modulation(VibeRate, VibeDepth);
// loop timer
if (loop0_timer >= LOOP0_DURATION) {
// update and check the pot
delayTimeKnob.update();
if (delayTimeKnob.hasChanged()) {
//Serial.printf("Delay Time Knob:%d\n", delayTimeKnob.getValue());
delay1.delaysmooth(0, delayTimeKnob.getValue());
}
loop0_timer = 0;
}
feedback = (float) analogRead (A2) / 1023; // delay feedback
mix = (float) analogRead (A0) / 1023; // wet/dry mix
//Serial.println (mix);
mix1 = 1.0 - mix;
amp1.gain(1);
//Set mixer levels
mixer1.gain (0, 0.5); // clean gtr in level
mixer1.gain (1, feedback);
mixer1.gain (2, 1);
mixer2.gain (0, mix); // fx signal
mixer2.gain (1, 0.5); // dry signal
// do bitcrushing
bitdepth = (16);
bitcrusher1.bits(bitdepth); // set bit depth
samplerate = (analogRead(A1) << 1) + 1000; // samplerate pot ranges from 1000 to 9190
bitcrusher1.sampleRate(samplerate); // set sample rate
bandpass = (analogRead(A3) << 1) + 1000; // lpf pot ranges from 500 to 8240hz
biquad1.setBandpass (0, 2000, 1);
biquad1.setBandpass (1, 2000, 1);
biquad1.setBandpass (2, 2000, 1);
biquad1.setBandpass (3, 2000, 1);
}
For reference, here is the same code without the LFO which works fine:
Code:
#define LED 3
#include <Bounce.h>
#include <ResponsiveAnalogRead.h>
#include <vibrato.h>
#include "effect_delay10tap.h"
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
//LFO BITS
//FX BITS
AudioInputI2S i2s1; //xy=82,344
AudioMixer4 mixer1; //xy=162,96
AudioEffectBitcrusher bitcrusher1; //xy=255,27
AudioEffectDelay10tap delay1; //xy=307,220
AudioAmplifier amp1; //xy=409,29
AudioMixer4 mixer2; //xy=462,224
AudioFilterStateVariable filter1; //xy=535,37
AudioFilterBiquad biquad1;
AudioOutputI2S i2s2; //xy=746,214
AudioEffect_Vibrato vibrato1;
//PATCHING
AudioConnection patchCord1(i2s1, 0, vibrato1, 0);
AudioConnection patchCord2(vibrato1, 0, mixer1, 0);
AudioConnection patchCord3(i2s1, 0, bitcrusher1, 0);
AudioConnection patchCord4(i2s1, 0, mixer2, 1);
AudioConnection patchCord5(mixer1, delay1);
AudioConnection patchCord6(bitcrusher1, amp1);
AudioConnection patchCord7(delay1, 0, mixer1, 1);
AudioConnection patchCord8(delay1, 0, mixer2, 0);
AudioConnection patchCord9(delay1, 1, mixer2, 2);
AudioConnection patchCord10(amp1, biquad1);
AudioConnection patchCord11(biquad1, filter1);
AudioConnection patchCord12(mixer2, 0, i2s2, 0);
AudioConnection patchCord13(filter1, 1, mixer1, 2);
AudioControlSGTL5000 sgtl5000_1; //xy=767,328
// GUItool: end automatically generated code
// delay line
#define DELAYLINE_MAX_LEN 45159 // number of samples at 44100 samples a second
int16_t delay_line[DELAYLINE_MAX_LEN] = {};
// main timing loop
#define LOOP0_DURATION 20 // interval time in millis
elapsedMillis loop0_timer;
// pot to control delaytime
const int DELAY_TIME_KNOB_PIN = A4; // A12 gain
ResponsiveAnalogRead delayTimeKnob(DELAY_TIME_KNOB_PIN, true);
/*
Bounce footswitch = Bounce(0, 50); // debounce the footswitch
Bounce D1 = Bounce(1, 50); // debounce the toggle switch
Bounce D2 = Bounce(2, 50); // " " " " " " " " "
// this section includes the function to check the toggle position
bool right;
bool middle;
bool left;
void checkToggle () { // this is our function to check toggle position...
D1.update(); D2.update(); // check digital inputs connected to toggle (can delete I think)
if (digitalRead(1) && !digitalRead(2)) {
right = 1; // toggle is right
middle = 0;
left = 0;
}
if (digitalRead(1) && digitalRead(2)) {
right = 0; // toggle is in the middle
middle = 1;
left = 0;
}
if (!digitalRead(1) && digitalRead(2)) {
right = 0; // toggle is left
middle = 0;
left = 1;
}
}
*/
byte bitdepth = 16; // used to set bit depth
int samplerate = 44100; // used to set sample rate
float mix; // clean/delay mix
float mix1; // clean/delay mix
float feedback; // delay feedback
int bandpass; //bandpass cutoff frequency
int delaytime;
void setup() {
AudioMemory(400); // the "40" represents how much internal memory (in the Teensy, not the external RAM chip) is allotted for audio recording. It is measured in sample blocks, each providing 2.9ms of audio.
sgtl5000_1.enable(); // this turns on the SGTL5000, which is the audio codec on the audio board
sgtl5000_1.volume(1); // this sets the output volume (it can be between 0 and 1)
sgtl5000_1.inputSelect(AUDIO_INPUT_LINEIN); // selects the audio input, we always use Line In
// analogReadResolution(10); // configure the pots to give 12 bit readings
pinMode(0, INPUT_PULLUP); // internal pull-up resistor for footswitch
pinMode(1, INPUT_PULLUP); // internal pull-up resistor for toggle
pinMode(2, INPUT_PULLUP); // internal pull-up resistor for toggle
pinMode(3, OUTPUT); // pin 3 (the LED) is an output;
Serial.begin(115200); // initiate the serial monitor. USB is always 12 Mbit/sec
sgtl5000_1.audioPostProcessorEnable();
//analogReadAveraging(10);
// start up the effect and pass it an array to store the samples
delay1.begin(delay_line, DELAYLINE_MAX_LEN);
}
float VibeRate = 1;
float VibeDepth = 10;
void loop() {
vibrato1.modulation(VibeRate, VibeDepth);
// loop timer
if (loop0_timer >= LOOP0_DURATION) {
// update and check the pot
delayTimeKnob.update();
if (delayTimeKnob.hasChanged()) {
//Serial.printf("Delay Time Knob:%d\n", delayTimeKnob.getValue());
delay1.delaysmooth(0, delayTimeKnob.getValue());
}
loop0_timer = 0;
}
feedback = (float) analogRead (A2) / 1023; // delay feedback
mix = (float) analogRead (A0) /1023; // wet/dry mix
//Serial.println (mix);
mix1 = 1.0 - mix;
amp1.gain(1);
//Set mixer levels
mixer1.gain (0, 0.5); // clean gtr in level
mixer1.gain (1, feedback);
mixer1.gain (2, 1);
mixer2.gain (0, mix); // fx signal
mixer2.gain (1, 0.5); // dry signal
// do bitcrushing
bitdepth = (16);
bitcrusher1.bits(bitdepth); // set bit depth
samplerate = (analogRead(A1) << 1) + 1000; // samplerate pot ranges from 1000 to 9190
bitcrusher1.sampleRate(samplerate); // set sample rate
bandpass = (analogRead(A3) << 1) + 1000; // lpf pot ranges from 500 to 8240hz
biquad1.setBandpass (0, bandpass, 2);
biquad1.setBandpass (1, bandpass, 2);
biquad1.setBandpass (2, bandpass, 2);
biquad1.setBandpass (3, bandpass, 2);
filter1.frequency (bandpass);
filter1.resonance (5);
filter1.octaveControl (5);
}
Last edited: