Trigger ADSR Example via Midi

How to trigger the ADSR example via Midi?

Hi Philoop,

What’s your electronics setup looking like? Do have the Daisy Seed with a TRS MIDI setup similar to the Pod? If so, I would recommend first trying out the Midi.ino example in the Pod example to make sure that your circuit is hooked up correctly before coding.

It is wired as the Pod, Hardware midi. I tested the Pod example, but it Triggers the Adenv with

void handleNoteOn(byte inChannel, byte inNote, byte inVelocity) {
  env.Trigger();
  osc.SetFreq(mtof(inNote));

I don`t understand how to trigger the ADSR.

Now i understand

// Title: adsr
// Description: Triangle wave controlled by adsr envelope
// Hardware: Daisy Seed
// Author: Ben Sergentanis

#include "DaisyDuino.h"
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#include <MIDI.h>

DaisyHardware hw;

size_t num_channels;

Adsr env;
Oscillator osc;
Metro tick;
bool gate;
byte note;

void MyCallback(float **in, float **out, size_t size) {
  float osc_out, env_out, ea;
  for (size_t i = 0; i < size; i++) {

    // When the metro ticks, trigger the envelope to start.
    /*if (tick.Process()) {
      gate = !gate;
    }*/
    
    // Use envelope to control the amplitude of the oscillator.
    env_out = env.Process(gate);
    osc.SetAmp(env_out);
    osc_out = osc.Process();

    for (size_t chn = 0; chn < num_channels; chn++) {
      out[chn][i] = osc_out;
    }
  }
}

void setup() {
  float samplerate;
  // Initialize for Daisy pod at 48kHz
  hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K);
  num_channels = hw.num_channels;
  samplerate = DAISY.get_samplerate();

  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.turnThruOff();

  MIDI.setHandleNoteOn(handleNoteOn);
  MIDI.setHandleNoteOff(handleNoteOff);
  Serial.begin(9600);
  

  env.Init(samplerate);
  osc.Init(samplerate);

  // Set up metro to pulse every second
  tick.Init(1.0f, samplerate);

  // Set envelope parameters
  env.SetTime(ADSR_SEG_ATTACK, .1);
  env.SetTime(ADSR_SEG_DECAY, .1);
  env.SetTime(ADSR_SEG_RELEASE, .01);

  env.SetSustainLevel(.25);

  // Set parameters for oscillator
  osc.SetWaveform(osc.WAVE_TRI);
  osc.SetFreq(220);
  osc.SetAmp(0.25);

  DAISY.begin(MyCallback);
}

void handleNoteOn(byte inChannel, byte inNote, byte inVelocity) {
     gate = 1;
     osc.SetFreq(mtof(inNote));
    // env.Retrigger(gate);
    
     Serial.print(inChannel);
     Serial.print("t");
     Serial.print(inNote);
     Serial.print("t");
     Serial.println(inVelocity);
     }  

void handleNoteOff(byte inChannel, byte inNote, byte offVelocity) {
      gate = 0;
     }

void loop() {
  MIDI.read();
  Serial.println(gate);
  }
1 Like

Now that i got it working, i would expect a short click,
using these settings:

 // Set envelope parameters
  env.SetTime(ADSR_SEG_ATTACK, .0);
  env.SetTime(ADSR_SEG_DECAY, .01);
  env.SetTime(ADSR_SEG_RELEASE, .00);
  env.SetSustainLevel(.0);

but I get a tone as long as the notelength. hm.

This is because you are not clearing ‘gate’ until Note Off.
To trigger the ADSR, you need to call Process() only once with gate set to 1.

Instead of

 env_out = env.Process(gate); 

Try this:

env_out = env.Process(gate); if(gate) gate = 0;

1 Like

That triggers the Adsr,(and clicks) but i am losing the gate/sustain then.

Sorry, I misread your problem. Ill give it a try later…

I’d suggest trying some different values, the fast attack makes it hard to discern the decay to sustain level. Maybe
Attack 1.0f
Decay 1.0f
Sustain 0.5f
Release 0.f
This way, you should see a 1 second rise to max level, a 1 second decay to 1/2 level, and a quick release when key is released.

I was using the tick example, there i couldnt get a click.My Midi example is working fine. Sorry for the noise. :upside_down_face:

1 Like

I added glide from https://github.com/treisti/303duino/blob/master/_303/_303.ino

// Title: adsr
// Description: Triangle wave controlled by adsr envelope
// Hardware: Daisy Seed
// Author: Ben Sergentanis
// Added glide from  https://github.com/treisti/303duino/blob/master/_303/_303.ino

#include "DaisyDuino.h"
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

byte legato_mode = 3;  //  off / on / glide / legato+glide
byte master_channel = 1;
int glide_range = 10000;

byte current_note = 0;
byte previous_note = 0;
int glide_step = 0;


DaisyHardware hw;

size_t num_channels;

Adsr env;
Oscillator osc;

bool gate;
int freq;


void MyCallback(float **in, float **out, size_t size) {
  float osc_out, env_out, ea;
  for (size_t i = 0; i < size; i++) {


    // Use envelope to control the amplitude of the oscillator.
    env_out = env.Process(gate);
    //if(gate) gate = 0;    //  tigger env instead of gate
    updateFrequency(glide_range);
    osc.SetAmp(env_out);
    osc_out = osc.Process();


    for (size_t chn = 0; chn < num_channels; chn++) {
      out[chn][i] = osc_out;
    }
  }
}

void setup() {
  float samplerate;
  // Initialize for Daisy pod at 48kHz
  hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K);
  num_channels = hw.num_channels;
  samplerate = DAISY.get_samplerate();

  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.turnThruOff();

  MIDI.setHandleNoteOn(handleNoteOn);
  MIDI.setHandleNoteOff(handleNoteOff);
  Serial.begin(9600);
  
  env.Init(samplerate);
  osc.Init(samplerate);

  // Set envelope parameters
  env.SetTime(ADSR_SEG_ATTACK, .1);
  env.SetTime(ADSR_SEG_DECAY, .1);
  env.SetTime(ADSR_SEG_RELEASE, .1);

  env.SetSustainLevel(.25);

  // Set parameters for oscillator
  osc.SetWaveform(osc.WAVE_TRI);
  osc.SetFreq(220);
  osc.SetAmp(0.25);

  DAISY.begin(MyCallback);
}

void handleNoteOn(byte inChannel, byte inNote, byte inVelocity) {
     
  if(inChannel == master_channel) {
    if(!current_note) {
      gate = 1;
    } else if(legato_mode == 0 || legato_mode == 2) {
      gate = 1;
    }
    
    previous_note = current_note;
    current_note = inNote;

    if(previous_note) {
      glide_step = 0;
    }
  }
     
    // env.Retrigger(gate);
    
     Serial.print(inChannel);
     Serial.print("t");
     Serial.print(inNote);
     Serial.print("t");
     Serial.println(inVelocity);
     }  

void handleNoteOff(byte inChannel, byte inNote, byte offVelocity) {
    if(inChannel == master_channel && current_note == inNote) {
     previous_note = 0;
     current_note = 0;
     gate = 0;
     }
   }

void updateFrequency(int glide_range) {
    float freq = mtof(current_note-12) ;

    if(previous_note && legato_mode >= 2 && glide_step < glide_range) {
      float previous_freq = mtof(previous_note-12);
      freq = previous_freq + glide_step * (freq - previous_freq) / glide_range;
      glide_step ++;
    }
    osc.SetFreq(freq);     
 }   

void loop() {
  MIDI.read();
  Serial.println(gate);
  Serial.println(freq);
  }

I have set the glide_range to 10000. But what are 10000 in ms ?