Forum Rule: Always post complete source code & details to reproduce any issue!

# Thread: LFO/VCO with Map & Constrain

1. ## LFO/VCO with Map & Constrain

Hi all,

I'm using 2 x waveforms going into a mixer & trying to map/constrain each so that one acts as an LFO and one acts as an audible range oscillator.
Having a strange issue where knob2/4 are mapping/constraining correctly, but knob6/7 does not seem to read the potentiometer whatsoever and stays at the same rate, regardless of the pot value unless map/constrain is done after the following line:

Code:
`waveform3.frequency(360 * knob6 + 0.25);`
Meaning that the mapping/constraining of the values is done after the frequency is set. So obviously does nothing.

In the commented code, you can see how I tried to do this initially.
I could not figure out how to do that way, by mapping/constraining waveform1.frequency, etc.
I do not have access to an oscilloscope until next week, but I was wondering what the maximum/minimum frequency of the waveform object is?
My guess was 20Hz-20kHz, hence 1.023 = 20Hz & 1023.0 = 20kHz...

Code:
```  // use the knobs to adjust parameters
//float knob1 = (float)analogRead(A1) / 1023.0;
float knob2 = (float)analogRead(A2) / 1023.0;
knob2 = map(knob2, 0.0, 1023.0, 0.0, 1.023);
knob2 = constrain(knob2, 0.0, 1.023);
waveform1.frequency(360 * knob2 + 0.25);

float knob3 = (float)analogRead(A3) / 1023.0;
sine_fm1.frequency(knob3 * 1500 + 50);

float knob6 = (float)analogRead(A18) / 1023.0;
waveform3.frequency(360 * knob6 + 0.25);
knob6 = map(knob6, 0.0, 1023.0, 1.023, 1023.0);
knob6 = constrain(knob6, 1.023, 1023.0);
//map(waveform1.frequency, 0.0, 20000.0, 0.0, 20.0);
//constrain(waveform1.frequency, 0.0, 20.0);
//map(waveform3.frequency, 0.0, 20000.0, 20.0, 20000.0);
//constrain(waveform3.frequency, 20.0, 20000.0);

float knob4 = (float)analogRead(A6) / 1023.0;
knob4 = map(knob4, 0.0, 1023.0, 0.0, 1.023);
knob4 = constrain(knob4, 0.0, 1.023);
waveform2.frequency(360 * knob4 + 0.25);

float knob5 = (float)analogRead(A7) / 1023.0;
sine_fm2.frequency(knob5 * 1500 + 50);

float knob7 = (float)analogRead(A20) / 1023.0;
waveform4.frequency(360 * knob7 + 0.25);
knob7 = map(knob7, 0.0, 1023.0, 1.023, 1023.0);
knob7 = constrain(knob7, 1.023, 1023.0);
//map(waveform1.frequency, 0.0, 20000.0, 0.0, 20.0);
//constrain(waveform1.frequency, 0.0, 20.0);
//map(waveform3.frequency, 0.0, 20000.0, 20.0, 20000.0);
//constrain(waveform3.frequency, 20.0, 20000.0);```
Any clarification on this would be much appreciated.

2. Apologies for not posting the complete code:
Code:
```#include <Bounce.h>

Bounce button0 = Bounce(0, 15);
Bounce button1 = Bounce(1, 15);  // 15 = 15 ms debounce time
Bounce button2 = Bounce(2, 15);

Bounce button3 = Bounce(3, 15);
Bounce button4 = Bounce(4, 15);  // 15 = 15 ms debounce time
Bounce button5 = Bounce(5, 15);
/*
Bounce button6 = Bounce(24, 15);
Bounce button7 = Bounce(25, 15);
*/
///////////////////////////////////
// copy the Design Tool code here
///////////////////////////////////

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveform       waveform1;      //xy=140,129
AudioSynthWaveform       waveform2;      //xy=170,392
AudioSynthWaveformSineModulated sine_fm2;       //xy=214,452
AudioSynthWaveformSineModulated sine_fm1;       //xy=219,187
AudioSynthWaveform       waveform3;      //xy=226,234
AudioSynthWaveform       waveform4;      //xy=235,498
AudioSynthKarplusStrong  string1;        //xy=242,535
AudioSynthSimpleDrum     drum1;          //xy=251,280
AudioEffectEnvelope      envelope1;      //xy=414,294
AudioMixer4              mixer1;         //xy=425,183
AudioEffectEnvelope      envelope2;      //xy=437,542
AudioMixer4              mixer3;         //xy=444,464
AudioMixer4              mixer2;         //xy=561,264
AudioMixer4              mixer4;         //xy=564,524
AudioOutputI2S           i2s1;           //xy=702,335
AudioConnection          patchCord1(waveform1, sine_fm1);
AudioConnection          patchCord2(waveform1, 0, mixer1, 0);
AudioConnection          patchCord3(waveform2, sine_fm2);
AudioConnection          patchCord4(waveform2, 0, mixer3, 0);
AudioConnection          patchCord5(sine_fm2, 0, mixer3, 2);
AudioConnection          patchCord6(sine_fm1, 0, mixer1, 2);
AudioConnection          patchCord7(waveform3, 0, mixer1, 1);
AudioConnection          patchCord8(waveform4, 0, mixer3, 1);
AudioConnection          patchCord9(string1, 0, mixer3, 3);
AudioConnection          patchCord10(drum1, 0, mixer1, 3);
AudioConnection          patchCord11(envelope1, 0, mixer2, 1);
AudioConnection          patchCord12(mixer1, 0, mixer2, 0);
AudioConnection          patchCord13(mixer1, envelope1);
AudioConnection          patchCord14(envelope2, 0, mixer4, 1);
AudioConnection          patchCord15(mixer3, 0, mixer4, 0);
AudioConnection          patchCord16(mixer3, envelope2);
AudioConnection          patchCord17(mixer2, 0, i2s1, 0);
AudioConnection          patchCord18(mixer4, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=424,110
// GUItool: end automatically generated code

void setup() {
Serial.begin(9600);
AudioMemory(20);
sgtl5000_1.enable();
sgtl5000_1.volume(0.32);

pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);

mixer1.gain(0, 0.75);
mixer1.gain(1, 0.0);
mixer1.gain(2, 0.0);
mixer1.gain(3, 0.0);
mixer2.gain(0, 0.15);
mixer2.gain(1, 0.0);
mixer2.gain(2, 0.0);
mixer2.gain(3, 0.0);
mixer3.gain(0, 0.75);
mixer3.gain(1, 0.0);
mixer3.gain(2, 0.0);
mixer3.gain(3, 0.0);
mixer4.gain(0, 0.15);
mixer4.gain(1, 0.0);
mixer4.gain(2, 0.0);
mixer4.gain(3, 0.0);

waveform1.begin(WAVEFORM_SAWTOOTH);
waveform1.amplitude(0.75);
waveform1.frequency(50);
waveform1.pulseWidth(0.15);
sine_fm1.frequency(440);
sine_fm1.amplitude(0.75);
waveform3.begin(WAVEFORM_SAWTOOTH);
waveform3.frequency(200);
waveform3.amplitude(0.75);
waveform3.pulseWidth(0.15);
//pink1.amplitude(0.75); //
envelope1.attack(10);
envelope1.hold(10);
envelope1.decay(25);
envelope1.sustain(0.4);
envelope1.release(70);

waveform2.begin(WAVEFORM_SAWTOOTH);
waveform2.amplitude(0.75);
waveform2.frequency(50);
waveform2.pulseWidth(0.15);
sine_fm2.frequency(440);
sine_fm2.amplitude(0.75);
waveform4.begin(WAVEFORM_SAWTOOTH);
waveform4.frequency(200);
waveform4.amplitude(0.75);
waveform4.pulseWidth(0.15);
//pink2.amplitude(0.75); //
envelope2.attack(10);
envelope2.hold(10);
envelope2.decay(25);
envelope2.sustain(0.4);
envelope2.release(70);
}

int waveform_type = WAVEFORM_SAWTOOTH;
int mixer1_setting = 0;
int mixer2_setting = 0;
int mixer3_setting = 0;
int mixer4_setting = 0;
elapsedMillis timeout = 0;
bool mixer2_envelope = false;
bool mixer4_envelope = false;

void loop() {
button0.update();
button1.update();
button2.update();
button3.update();
button4.update();
button5.update();
//button6.update();
//button7.update();

// Left changes the type of control waveform
if (button0.fallingEdge()) {
Serial.print("Control waveform 1: ");
if (waveform_type == WAVEFORM_SAWTOOTH) {
waveform_type = WAVEFORM_SINE;
Serial.println("Sine");
} else if (waveform_type == WAVEFORM_SINE) {
waveform_type = WAVEFORM_SQUARE;
Serial.println("Square");
} else if (waveform_type == WAVEFORM_SQUARE) {
waveform_type = WAVEFORM_TRIANGLE;
Serial.println("Triangle");
} else if (waveform_type == WAVEFORM_TRIANGLE) {
waveform_type = WAVEFORM_PULSE;
Serial.println("Pulse");
} else if (waveform_type == WAVEFORM_PULSE) {
waveform_type = WAVEFORM_SAWTOOTH;
Serial.println("Sawtooth");
}
waveform1.begin(waveform_type);
waveform3.begin(waveform_type);
}

if (button3.fallingEdge()) {
Serial.print("Control waveform 2: ");
if (waveform_type == WAVEFORM_SAWTOOTH) {
waveform_type = WAVEFORM_SINE;
Serial.println("Sine");
} else if (waveform_type == WAVEFORM_SINE) {
waveform_type = WAVEFORM_SQUARE;
Serial.println("Square");
} else if (waveform_type == WAVEFORM_SQUARE) {
waveform_type = WAVEFORM_TRIANGLE;
Serial.println("Triangle");
} else if (waveform_type == WAVEFORM_TRIANGLE) {
waveform_type = WAVEFORM_PULSE;
Serial.println("Pulse");
} else if (waveform_type == WAVEFORM_PULSE) {
waveform_type = WAVEFORM_SAWTOOTH;
Serial.println("Sawtooth");
}
waveform2.begin(waveform_type);
waveform4.begin(waveform_type);
}

// middle button switch which source we hear from mixer1
if (button1.fallingEdge()) {
if (mixer1_setting == 0) {
mixer1.gain(0, 0.75);
mixer1.gain(1, 0.0);
mixer1.gain(2, 0.0);
mixer1.gain(3, 0.0);
Serial.println("Mixer1: LFO");
mixer1_setting = 1;
} else if (mixer1_setting == 1) {
mixer1.gain(0, 0.0);
mixer1.gain(1, 0.75);
mixer1.gain(2, 0.0);
mixer1.gain(3, 0.0);
Serial.println("Mixer1: VCO");
mixer1_setting = 2;
} else if (mixer1_setting == 2) {
mixer1.gain(0, 0.0);
mixer1.gain(1, 0.0);
mixer1.gain(2, 0.75);
mixer1.gain(3, 0.0);
Serial.println("Mixer1: FM");
mixer1_setting = 3;
} else if (mixer1_setting == 3) {
mixer1.gain(0, 0.0);
mixer1.gain(1, 0.0);
mixer1.gain(2, 0.0);
mixer1.gain(3, 0.75);
Serial.println("Mixer1: DRUM");
mixer1_setting = 0;
}
}

if (button4.fallingEdge()) {
if (mixer3_setting == 0) {
mixer3.gain(0, 0.75);
mixer3.gain(1, 0.0);
mixer3.gain(2, 0.0);
mixer3.gain(3, 0.0);
Serial.println("Mixer3: LFO");
mixer3_setting = 1;
} else if (mixer3_setting == 1) {
mixer3.gain(0, 0.0);
mixer3.gain(1, 0.75);
mixer3.gain(2, 0.0);
mixer3.gain(3, 0.0);
Serial.println("Mixer3: VCO");
mixer3_setting = 2;
} else if (mixer3_setting == 2) {
mixer3.gain(0, 0.0);
mixer3.gain(1, 0.0);
mixer3.gain(2, 0.75);
mixer3.gain(3, 0.0);
Serial.println("Mixer3: FM");
mixer3_setting = 3;
} else if (mixer3_setting == 3) {
mixer3.gain(0, 0.0);
mixer3.gain(1, 0.0);
mixer3.gain(2, 0.0);
mixer3.gain(3, 0.75);
Serial.println("Mixer3: STRING");
mixer3_setting = 0;
}
}

// Right button activates the envelope
if (button2.fallingEdge()) {
mixer2.gain(0, 0.0);
mixer2.gain(1, 1.0);
mixer2_envelope = true;
timeout = 0;
envelope1.noteOn();
}
if (button2.risingEdge()) {
envelope1.noteOff();
timeout = 0;
}

if (button5.fallingEdge()) {
mixer4.gain(0, 0.0);
mixer4.gain(1, 1.0);
mixer4_envelope = true;
timeout = 0;
envelope2.noteOn();
}
if (button5.risingEdge()) {
envelope2.noteOff();
timeout = 0;
}

// after 4 seconds of inactivity, go back to
if (mixer2_envelope == true && timeout > 4000) {
mixer2.gain(0, 0.15);
mixer2.gain(1, 0.0);
mixer2_envelope = false;
}

if (mixer4_envelope == true && timeout > 4000) {
mixer4.gain(0, 0.15);
mixer4.gain(1, 0.0);
mixer4_envelope = false;
}
/*
if (button6.fallingEdge) {
Serial.println("VCO");
constrain(waveform1.frequency, 20.0, 20000.0)

else if ({
Serial.println("VCO");
constrain(waveform1.frequency, 20.0, 20000.0)
})
}
*/
// use the knobs to adjust parameters
//float knob1 = (float)analogRead(A1) / 1023.0;
float knob2 = (float)analogRead(A2) / 1023.0;
knob2 = map(knob2, 0.0, 1023.0, 0.0, 1.023);
knob2 = constrain(knob2, 0.0, 1.023);
waveform1.frequency(360 * knob2 + 0.25);

float knob3 = (float)analogRead(A3) / 1023.0;
sine_fm1.frequency(knob3 * 1500 + 50);

float knob6 = (float)analogRead(A18) / 1023.0;
waveform3.frequency(360 * knob6 + 0.25);
knob6 = map(knob6, 0.0, 1023.0, 1.023, 1023.0);
knob6 = constrain(knob6, 1.023, 1023.0);
//map(waveform1.frequency, 0.0, 20000.0, 0.0, 20.0);
//constrain(waveform1.frequency, 0.0, 20.0);
//map(waveform3.frequency, 0.0, 20000.0, 20.0, 20000.0);
//constrain(waveform3.frequency, 20.0, 20000.0);

float knob4 = (float)analogRead(A6) / 1023.0;
knob4 = map(knob4, 0.0, 1023.0, 0.0, 1.023);
knob4 = constrain(knob4, 0.0, 1.023);
waveform2.frequency(360 * knob4 + 0.25);

float knob5 = (float)analogRead(A7) / 1023.0;
sine_fm2.frequency(knob5 * 1500 + 50);

float knob7 = (float)analogRead(A20) / 1023.0;
waveform4.frequency(360 * knob7 + 0.25);
knob7 = map(knob7, 0.0, 1023.0, 1.023, 1023.0);
knob7 = constrain(knob7, 1.023, 1023.0);
//map(waveform1.frequency, 0.0, 20000.0, 0.0, 20.0);
//constrain(waveform1.frequency, 0.0, 20.0);
//map(waveform3.frequency, 0.0, 20000.0, 20.0, 20000.0);
//constrain(waveform3.frequency, 20.0, 20000.0);
}```
My aim is for this to be made for Eurorack, hence the left and right channels acting as separate mono channels.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•