Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

Thread: LFO/VCO with Map & Constrain

  1. #1
    Junior Member
    Join Date
    May 2018
    Posts
    11

    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. #2
    Junior Member
    Join Date
    May 2018
    Posts
    11
    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
      // steady listening instead of the envelope
      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.

  3. #3
    Junior Member
    Join Date
    May 2018
    Posts
    11
    Anyone have any clue about this, it seems like a really strange problem.

  4. #4
    Junior Member
    Join Date
    May 2018
    Posts
    11
    Quote Originally Posted by Lightbluehue View Post
    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...
    Sorry, meant to say 0Hz-20kHz here. 20Hz for the audible rate oscillator.
    Also I am using the beta, does the above issue relate to that possibly?

Tags for this Thread

Posting Permissions

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