Pages: [1]   Go Down
Author Topic: Midi Library Note Overlap  (Read 2064 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Hi everyone

I'm hoping someone might be able to help me with a problem i am having. I am not the greatest at coding in the world, and you guys have been marvellous in the past and i thank you in advance for any assistance you can give. I have been banging my head against the wall for some time.

I'm doing an explenation of MIDI and CV for those who don't use it . just in case someone can help

The problem i am having concerns Midi and in particular the use of this midi library
https://github.com/FortySevenEffects/arduino_midi_library which is great

The project I am working on involves a Midi to Control Voltage / Gate Voltage convertor which controls an old Synthesiser. Basically you play a note on a keyboard which is Midi equipped this goes into the Arduino via a midi circuit. When you play a note i am using the Library which allows me to convert the Midi note number to a voltage using a DAC + circuit . This is feed into the synth CV input which controls the pitch.  The library also allows me to convert a Note On message into a Gate Voltage which is feed into the synth this triggers an envelope which allows me to hear the note, and when a Note Off message is sent  the envelope closes and therefore the note is muted (I am using digital out 8 for this task).

There are two types of midi Note Off message a traditional Note Off message and a Note Off message which is actually a Note On with zero velocity.  Both can be handled by the library but my problem is concerned with the Note Off with zero velocity. I am not going through any Computer sequencer package but directly from my Midi Keyboard into the Arduino which sends out midi using the Note Off's with zero velocity standard.

The code I am posting is a stripped down version of a much larger program I have compressed the code for the DAC to make it easier to scroll and the DAC is not a problem.

So what is the problem well actually everything works. When you play a note the dac sends out a voltage the Gate opens this triggers the synth and all is hunky dory.
what I am trying to introduce is the following: (allow the overlap of notes)

When you press a note down the gate opens and a note is heard .If you release the note the gate shuts and the note is muted (great)
If you do the above again but this time because of the speed you are playing (for example) you hit a second note whilst still holding down the first note, the pitch changes which is great but when you release the key on the first note it shuts down the gate and obviously cuts of the second note. (not great)
So i thought to myself i would try using an array when a note is hit firstly it moves what is in position 0 of the array to position 1, then it puts a number in position 0. (thought I had it)
So i thought when the Note of command is sent it would clear the array. because i thought the Note Off command follows the note on command. If it worked how i wanted it to if two notes were pressed i would have an array that i could sum and use that number if it was over 19 in this case (usually it would be 10) then i could say don't shut the gate till the second note is released.

But obviously I have found that it doesn't work like that and the note off command as it says on the tin…. is a new note so my array is always summed at twenty

I really hope that makes sense
I'm totally out of ideas ……..please can you help…….thanks for reading

here is where i'm up to
For those who know the library I have engaged the note off as zero velocity in the settings
there is two if's wrapped around the DAC voltage as I'm using different Zones in the larger program.

I'm really sorry if my code looks big I can't reduce the font size (i'm not having a good week)


Code:


#include <MIDI.h>
   #define LATCH 7  //Variable for DAC
   #define CLOCK 6  //Variable for DAC
   #define DATA  4  //Variable for DAC
   #define HALF_CLOCK_PERIOD 1   //Variable for DAC
uint16_t DACoutput=530;  //Variable for DAC
int led = 8; // Opens Gate
//test variable
int x = 0;
byte truthArray[2]={10,0};
byte sumArray = 0;
byte gate = 0;
byte problem = 0;

void setup(){
  Serial.begin(31250);
  MIDI.setHandleNoteOn(HandleNoteOn);
  MIDI.begin(1);//Launch MIDI and listen to channel 1
  pinMode(led,OUTPUT); //Opens Gate
  //DAC setup pins
  pinMode(DATA, OUTPUT);pinMode(CLOCK,OUTPUT);pinMode(LATCH,OUTPUT);digitalWrite(DATA,LOW);digitalWrite(CLOCK,LOW);digitalWrite(LATCH,LOW);
  }// end of setup

void loop()
  {
    MIDI.read();
  }// End of void loop
 


 void HandleNoteOn(byte channel,byte note,byte velocity){
   digitalWrite(led,HIGH);
 
if ( note > 10){if (note < 128){DACoutput = note * 300; writeValue(DACoutput);
                                //this is my idea but it didn't work
                               // truthArray[1]=truthArray[0]; truthArray[0]=10;sumArray = truthArray[0] + truthArray[1];
                              
                                 }}//End of if ( note > 10){if (note < 128)
  
 
if (velocity == 0){digitalWrite(led,LOW);}//clear array code was in here

} //end of HandleNoteOn
 
 
 

 
 // ad420 Bit DAC Code compressed
  void writeValue(uint16_t value){ //start of sequence
      digitalWrite(LATCH,LOW);digitalWrite(CLOCK,LOW);for(int i=15;i>=0;i--){digitalWrite(DATA,((value&(1<<i)))>>i);
      delayMicroseconds(HALF_CLOCK_PERIOD);digitalWrite(CLOCK,HIGH);delayMicroseconds(HALF_CLOCK_PERIOD);digitalWrite(CLOCK,LOW);}
      digitalWrite(DATA,LOW);digitalWrite(CLOCK,LOW);digitalWrite(LATCH,HIGH);delayMicroseconds(HALF_CLOCK_PERIOD);digitalWrite(LATCH,LOW);}
      









Logged

Argentina
Offline Offline
Full Member
***
Karma: 5
Posts: 138
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I didn't check closely the code(no time now) But I can imagine what you coded for what you say.
I see you put this
 
Code:
if (velocity == 0){digitalWrite(led,LOW);}//clear array code was in here
I suppose led is the gate output. And of course, if you release any of the keys you pressed, it'll make it go off, even if you're holding
another note, because MIDI is serial. An easy escape is, make two counters, one that sums one when a note on is received
and another one that sums one when a noteoff is received. So, before bringing the gate output low, compare the two counters
and if they're the same, the gate goes off.
For example, you play three note on
note on -> counter 1
note on -> counter 2
note on - > counter 3
we have the counter at 3 here, now with the note off
note off -> counter2 1
note off -> counter2 2
note off -> counter2 3
now if they're the same, gate off. This way, the gate will go low when you release ALL the keys, like it should be. So you can play
legato
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

that worked just as you said it would
I have learnt something new
Thank you so much
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi

I thank capicoso for his wisdom and reply and the approach to the code did indeed work.

I have again been banging my head against a wall for a week now
to try and improve this approach.

with the code which has been implemented using capicoso approach

if i play a note say C (all great plays a C)
then while C is still pressed play note D (all is great plays a D)
if i then release D while C is still pressed I would like it to go back to playing a C
at the moment it still plays a D

its like i want to achieve a current status on the current note

I hoping someone might be able to unlock me going round and round in circles

thanking you in advance

Code:
#include <MIDI.h>
   #define LATCH 7  //Variable for DAC
   #define CLOCK 6  //Variable for DAC
   #define DATA  4  //Variable for DAC
   #define HALF_CLOCK_PERIOD 1   //Variable for DAC
uint16_t DACoutput=530;  //Variable for DAC
int led = 8; // Opens Gate
//test variable

byte noteOnCounter=0;
byte noteOffCounter = 0;

void setup(){
  Serial.begin(31250);
  MIDI.setHandleNoteOn(HandleNoteOn);
  MIDI.begin(1);//Launch MIDI and listen to channel 1
  pinMode(led,OUTPUT); //Opens Gate
  //DAC setup pins
  pinMode(DATA, OUTPUT);pinMode(CLOCK,OUTPUT);pinMode(LATCH,OUTPUT);digitalWrite(DATA,LOW);digitalWrite(CLOCK,LOW);digitalWrite(LATCH,LOW);
  }// end of setup

void loop()
  {
    MIDI.read();
  }// End of void loop
 


 void HandleNoteOn(byte channel,byte note,byte velocity){
digitalWrite(led,HIGH);
     
 
if (velocity > 0){//if its a real note
if ( note > 10){if (note < 128){DACoutput = note * 300; writeValue(DACoutput);
                              noteOnCounter++;
                              if (noteOnCounter == 4){noteOnCounter = 0;}
                               
                                 }}//End of if ( note > 10){if (note < 128)
                                 }//end of if velocity > 0
 
if (velocity == 0) {noteOffCounter++;if (noteOffCounter == 4){noteOffCounter = 0;}
if (noteOnCounter == noteOffCounter){ digitalWrite(led,LOW);} }

} //end of HandleNoteOn



 
 
 

 
 // ad420 Bit DAC Code compressed
  void writeValue(uint16_t value){ //start of sequence
      digitalWrite(LATCH,LOW);digitalWrite(CLOCK,LOW);for(int i=15;i>=0;i--){digitalWrite(DATA,((value&(1<<i)))>>i);
      delayMicroseconds(HALF_CLOCK_PERIOD);digitalWrite(CLOCK,HIGH);delayMicroseconds(HALF_CLOCK_PERIOD);digitalWrite(CLOCK,LOW);}
      digitalWrite(DATA,LOW);digitalWrite(CLOCK,LOW);digitalWrite(LATCH,HIGH);delayMicroseconds(HALF_CLOCK_PERIOD);digitalWrite(LATCH,LOW);}
     















Logged

Argentina
Offline Offline
Full Member
***
Karma: 5
Posts: 138
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I didn't remember it was for a midi 2 cv project.
First you should auto format your sketch, I can't follow the lines, very hard to read.
what is this for?
if (noteOnCounter == 4){noteOnCounter = 0;}
i would make the counters 0 when they're equal.
You can use arrays and store let's say, the last 4 notes. And when a noteoff is sent, read the note before that one. If you're holding more than two keys, well, which one will be played when the last one is released? You can choose to do it by pitch order, for example:
I play legato in this order, 60, 66, 70. I have them all pressed. So they're stored in array pos 0, 1 and 2. If the last one is released, read array position 1, and so on. I'm not sure how older keyboards used to work, for example, if the latest key was 66(the middle) i'm not sure which should play next, if 60, or 70. You can do it by order of pitch, or order of time. I would do it with pitch
Logged

Pages: [1]   Go Up
Jump to: