Adding note delay

Hey folks,

I am currently struggling with my code and specifically how to add a sort of delay to it. What I have been trying to do is stop the arduino from sending notes out that are shorter than around 20-30ms, I tried to add an interval that would count the time between the note being played and when the note turned off and then saying if the note length/interval was less than 50ms it wouldn't send to MIDI. I don't know if something like this is possible but it wasn't working so any help would be greatly appreciated.

#include <Filters.h>


//clipping indicator variables
boolean clipping = 0;

//data storage variables
byte newData = 0;
byte prevData = 0;
unsigned int time = 0;    //keeps time and sends vales to store in timer[] occasionally
int timer[10];            //sstorage for timing of events
int slope[10];            //storage fro slope of events
unsigned int totalTimer;  //used to calculate period
unsigned int period;      //storage for period of wave
byte index = 0;           //current storage index
float frequency;          //storage for frequency calculations
int maxSlope = 0;         //used to calculate max slope as trigger point
int newSlope;             //storage for incoming slope data

//variables for decided whether you have a match
byte noMatch = 0;   //counts how many non-matches you've received to reset variables if it's been too long
byte slopeTol = 3;  //slope tolerance- adjust this if you need (original value =3)
int timerTol = 10;  //timer tolerance- adjust this if you need (original value =10)

//for MIDI instructions
constexpr int noteON = 144;   //144 = 10010000 in binary, note on command
constexpr int noteOFF = 128;  //128 = 10000000 in binary, note off command

int velocity = 100;


//Full spectrum of notes


unsigned int MIDI_FREQUENCY[]{
  //  C     C-sharp   D     D-sharp   E     F     F-sharp   G     G-sharp   A     A-sharp   B
  8, 9, 9, 10, 10, 11, 12, 12, 13, 14, 15, 15,                             // Octave -1
  16, 17, 18, 19, 21, 22, 23, 25, 26, 28, 29, 31,                          // Octave 0
  33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62,                          // Octave 1
  65, 69, 73, 78, 82, 87, 93, 98, 104, 110, 117, 123,                      // Octave 2
  131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,              // Octave 3
  262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,              // Octave 4
  523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988,              // Octave 5
  1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976,  // Octave 6
  2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,  // Octave 7
  4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902,  // Octave 8
  8372, 8870, 9397, 9956, 10548, 11175, 11840, 12544                       // Octave 9 (partial)
};


const uint8_t MIDI_NOTE_C0 = 52;
const uint8_t MIDI_NOTE_C9 = 81;
static byte LastNote = 0;

//DSP filter code
float lowFrequency = 165;  // test signal frequency (Hz)
float highFrequency = 880;
float testAmplitude = 100;  // test signal amplitude
float testOffset = 100;

float windowLength = 20.0 / lowFrequency;  // how long to average the signal, for statistist

float testSignalSigma = testAmplitude / sqrt(2.0);       // the RMS amplitude of the test signal
float testSignal3dbSigma = testSignalSigma / sqrt(2.0);  // the RMS amplitude of the test signal, down -3db

float printPeriod = 5.0;

// return the current time
float filtertime() {
  return float(micros()) * 1e-6;
}

void setup() {
  Serial.begin(9600);

  pinMode(13, OUTPUT);  //led indicator pin
  pinMode(12, OUTPUT);  //output pin

  cli();  //diable interrupts

  //set up continuous sampling of analog pin 0 at 38.5kHz

  //clear ADCSRA and ADCSRB registers
  ADCSRA = 0;
  ADCSRB = 0;

  ADMUX |= (1 << REFS0);  //set reference voltage
  ADMUX |= (1 << ADLAR);  //left align the ADC value- so we can read highest 8 bits from ADCH register only

  ADCSRA |= (1 << ADPS2) | (1 << ADPS0);  //set ADC clock with 32 prescaler- 16mHz/32=500kHz
  ADCSRA |= (1 << ADATE);                 //enabble auto trigger
  ADCSRA |= (1 << ADIE);                  //enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN);                  //enable ADC
  ADCSRA |= (1 << ADSC);                  //start ADC measurements

  sei();  //enable interrupts
}

ISR(ADC_vect) {  //when new ADC value ready

  PORTB &= B11101111;                           //set pin 12 low
  prevData = newData;                           //store previous value
  newData = ADCH;                               //get value from A0
  if (prevData < 127 && newData >= 127) {       //if increasing and crossing midpoint
    newSlope = newData - prevData;              //calculate slope
    if (abs(newSlope - maxSlope) < slopeTol) {  //if slopes are ==
      //record new data and reset time
      slope[index] = newSlope;
      timer[index] = time;
      time = 0;
      if (index == 0) {      //new max slope just reset
        PORTB |= B00010000;  //set pin 12 high
        noMatch = 0;
        index++;                                                                                    //increment index
      } else if (abs(timer[0] - timer[index]) < timerTol && abs(slope[0] - newSlope) < slopeTol) {  //if timer duration and slopes match
        //sum timer values
        totalTimer = 0;
        for (byte i = 0; i < index; i++) {
          totalTimer += timer[i];
        }
        period = totalTimer;  //set period
        //reset new zero index values to compare with
        timer[0] = timer[index];
        slope[0] = slope[index];
        index = 1;           //set index to 1
        PORTB |= B00010000;  //set pin 12 high
        noMatch = 0;
      } else {    //crossing midpoint but not match
        index++;  //increment index
        if (index > 9) {
          reset();
        }
      }
    } else if (newSlope > maxSlope) {  //if new slope is much larger than max slope
      maxSlope = newSlope;
      time = 0;  //reset clock
      noMatch = 0;
      index = 0;  //reset index
    } else {      //slope not steep enough
      noMatch++;  //increment no match counter
      if (noMatch > 9) {
        reset();
      }
    }
  }

  if (newData == 0x00 || newData == 0xFF) {  //if clipping
    PORTB |= B00100000;                      //set pin 13 high- turn on clipping indicator led
    clipping = 1;                            //currently clipping
  }

  time++;  //increment timer at rate of 38.5kHz
}

void reset() {   //clea out some variables
  index = 0;     //reset index
  noMatch = 0;   //reset match couner
  maxSlope = 0;  //reset slope
}

void checkClipping() {   //manage clipping indicator LED
  if (clipping) {        //if currently clipping
    PORTB &= B11011111;  //turn off clipping indicator led
    clipping = 0;
  }
}

void testOnePoleFilters() {
  // filters are test with a sine wave input, keep track of those values here for a sanity check
  RunningStatistics inputStats;  // create statistics to look at the raw test signal
  inputStats.setWindowSecs(windowLength);

  FilterOnePole filterOneLowpass(LOWPASS, lowFrequency);  // create a one pole (RC) lowpass filter
  RunningStatistics filterOneLowpassStats;                // create running statistics to smooth these values
  filterOneLowpassStats.setWindowSecs(windowLength);

  FilterOnePole filterOneHighpass(HIGHPASS, highFrequency);  // create a one pole (RC) highpass filter
  RunningStatistics filterOneHighpassStats;                  // create running statistics to smooth these values
  filterOneHighpassStats.setWindowSecs(windowLength);

  float startTime = filtertime();
  float nextPrintTime = filtertime();

  while (true) {
    // update all real time classes
    float inputValue = testAmplitude + testAmplitude * sin(TWO_PI * lowFrequency * filtertime());

    // update the test value statistics
    inputStats.input(inputValue);

    // update the one pole lowpass filter, and statistics
    filterOneLowpass.input(inputValue);
    filterOneLowpassStats.input(filterOneLowpass.output());

    // update the one pole highpass filter, and statistics
    filterOneHighpass.input(inputValue);
    filterOneHighpassStats.input(filterOneHighpass.output());
  }
}


void loop() {
  checkClipping();

  frequency = 38462 / float(period);  //calculate frequency timer rate/period



  for (byte note = MIDI_NOTE_C0; note < MIDI_NOTE_C9; note++) {

    if (frequency < (MIDI_FREQUENCY[note] + MIDI_FREQUENCY[note + 1]) / 2) {

      // Matching note!
      if (note != LastNote)  
      {
        {

          // The note has changed so turn off the previous note
          MIDImessage(noteOFF, LastNote, velocity);
          MIDImessage(noteON, note, velocity);
        }
      }

      LastNote = note;
      break;  // No need to look for more matches.
    }
  }
}

//send MIDI message
void MIDImessage(byte command, byte MIDInote, byte MIDIvelocity) {
  Serial.write(command);       //send note on or note off command
  Serial.write(MIDInote);      //send pitch data
  Serial.write(MIDIvelocity);  //send velocity data
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.