Go Down

Topic: MIDI.getSysexArray - How to flusch the returned message? (Read 832 times) previous topic - next topic

reblochon

Hello,

Using <midi.h> library V3.2, I just try basically to have a diode blinking when a specific Sysex comes in.

Indeed, my MIDI device sends at each beat the same SysexMessage, where byte[5]==0x10. So I 'd like to have the tempo blinking.

So I wrote the following program :

Code: [Select]
#include <LiquidCrystal.h>
#include <MIDI.h>

const byte *  MyArray;
int ledPin = 13;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{
  pinMode(ledPin, OUTPUT);     
  lcd.begin(16,2);
  MIDI.begin();
  MIDI.turnThruOff();
}

void loop()
{
  MIDI.read();
  MyArray = MIDI.getSysExArray();
  lcd.setCursor(0,0);
  lcd.print(MyArray[5]);
  if ((MyArray[5])==0x10 )
    {
    digitalWrite(ledPin, HIGH);
    }
     
  else if ((MyArray[5])!=0x10 )
    {
    digitalWrite(ledPin, LOW);   
    }
}



As a result, the diode remains HIGH. It never comes down to the LOW state. When monitoring on the lcd MyArray[5] byte, it remains 0x10 all the time.

So I was wondering what's returned by "MIDI.GetSysExArray" request between 2 SysEx message received?
Does the function keeps in memory the last Sysex message?
If yes, is there a way to flush it?

Lionel

PaulS

Code: [Select]
  lcd.print(MyArray[5]);
How do YOU know how big the message is? There is nothing that is checking that 5 is a valid index.

Quote
Does the function keeps in memory the last Sysex message?

Yes, it does.

Quote
If yes, is there a way to flush it?

No, but you shouldn't need to.

You could quit ignoring the message type that was received, and pay attention to whether or not the last message was a sysex message.

Franky

Hello,

What you can do is the following:

Code: [Select]

void handleSysEx(byte* inData, byte inSize)
{
    if (inSize > 5)
    {
        if (inData[5] == 0x10)
            digitalWrite(ledPin, HIGH);
        else
            digitalWrite(ledPin, LOW);
    }
}

void setup()
{
    MIDI.begin();
    MIDI.setHandleSystemExclusive(handleSysEx);
}

void loop()
{
    MIDI.read();
}




Regarding your problem, are you sure there is another SysEx message with the fifth byte != 0x10 that is received, to turn off the LED?
If you want to detect beat, you can check for other supported messages, like Clock or SMPTE. They also have callbacks, although I think I fixed a few bugs in these since version 3.2.
The latest version is always available on GitHub:
https://github.com/FortySevenEffects/arduino_midi_library

Cheers!

Franky.

reblochon

Hi!
Thanks a lot for your answers :)!

First, the MIDI device (Axe-Fx 2) I use sends at each beat the following SysEx message (HEX):
{F0 00 01 74 03 10 F7}
So if tempo is 60, this message is sent once per second. I verified this by monitoring the MIDI out of the AF2 on my Digital Audio Worstation (Cubase). Nothing else comes.
And, except on request (unsing a specific SysEx code for example), the AF2 sends nothing else between 2 SysEx tempo message.

On the other hand, if I use another MIDI device that sends nothing on "idle", and if I request a "getSysExArray" to this other device, then the byte [5] returned is == 0.

Then Paul, to answer your point
Quote
How do YOU know how big the message is? There is nothing that is checking that 5 is a valid index.

I know it's a 7 byte array. But, even if there is no array, I get the value "0" in byte [5] (of course this is in case I did not receive previously a SysEx message) . 

Regarding
Quote
You could quit ignoring the message type that was received, and pay attention to whether or not the last message was a sysex message.

The last message is always the same SysEx.

Francky, I tested the code you suggested. And Finally I got the led High all time. It only gets on the LOW state when I send another SysEx message where byte[5] != 0x10. So it does not blink with tempo.

Quote
Regarding your problem, are you sure there is another SysEx message with the fifth byte != 0x10 that is received, to turn off the LED?

Indeed there is no other SysEx message received between.  =(

Quote
If you want to detect beat, you can check for other supported messages, like Clock or SMPTE.
Yeah I'd like to, but actully I receive nothing else but this tempo SysEx array.

Finally, I do use you latest version of the Library, but I have not yet tried to understand what are CallBacks.

Do you know if I can find or build a function (newbe level...) that could differenciate 2 identical SysEx array thanks only to lets say... their time of arrival  XD?

Cheers !!

Lionel


Franky

If you can only set the LED high when you receive the beat message, then you could use a counter variable to turn off the LED after a few calls of the loop() method when no message has been received.

The SysEx buffer will contain valid data only when a SysEx message is received, and should not be used when other messages are received (or no message at all).

Callbacks are functions that you ask the library to call when a kind of message is received. It makes the handling of MIDI input much easier (and faster) than a big block of if/else in the loop..

reblochon

#5
Dec 19, 2012, 08:30 pm Last Edit: Dec 19, 2012, 08:43 pm by reblochon Reason: 1
Hello Francky,
If I turn of the led after a few loop, it turns off, indeed. But as soon as I will send a GetSysExArray, it will return message from the SysEx buffer right? So it will be the previous message and will turn on the led not because a new message has arrived, but because there is still the message in the buffer.
Is there a way to know if it is read from a new message arrived, and not from the buffer?

Lionel

Franky

The point of the callback is that it's called only when a new message is received. You should not need to access the SysEx buffer anyway, since it is passed as an argument of your callback function.

The following code should do what you need:

Code: [Select]

#include <MIDI.h>

static const unsigned gLedPin = 13;

// Number of loops until turning off the led.
static const unsigned gLedCounterThreshold = 100;
unsigned gLedCounter = 0;

// -----------------------------------------------------------------------------

void handleSysEx(byte* inData, byte inSize)
{
    if (inSize > 5 && inData[5] == 0x10)
    {
        digitalWrite(gLedPin, HIGH);
        gLedCounter = gLedCounterThreshold;
    }
}

// -----------------------------------------------------------------------------

void setup()
{
    pinMode(gLedPin, OUTPUT);
    MIDI.begin();
    MIDI.turnThruOff();
    MIDI.setHandleSystemExclusive(handleSysEx);
    gLedCounter = 0;
}

void loop()
{
    MIDI.read();
    if (digitalRead(gLedPin) && gLedCounter-- == 0)
    {
        digitalWrite(gLedPin, LOW);
    }
}


reblochon

XD Hello Francky ! Your program is now working perfectly!!!
Thank you soooooo much :)!
I'll now get a closer look to understand it!!!
Thanks again,
Lionel

Go Up