How can I read an incoming midi clock and display as bpm?
What would an incoming midi clock look like ?
I’ve no idea Bob, maybe pop back in a few days and see if anyone has answered us.
I’m using Arduino midi library, midi read in my loop sends an incoming midi clock straight through to the output, just figured I’d try to capture and display the bpm.
In the meantime, if you have google on your internets, you might try
display incoming midi clock arduino
or variations thereof. It looks like you aren't the first person to want to use this midi thing and microprocessors.
a7
This is a MIDI system common message 0xF1 followed by the byte 0nnndddd
Where nnn is the message type and dddd is the values.
Otherwise known as the MIDI Time Code Quarter Frame message.
This might be what I'm looking for
byte midi_start = 0xfa;
byte midi_stop = 0xfc;
byte midi_clock = 0xf8;
byte midi_continue = 0xfb;
int play_flag = 0;
byte data;
void setup() {
Serial.begin(31250);
}
void loop() {
if(Serial.available() > 0) {
data = Serial.read();
if(data == midi_start) {
play_flag = 1;
}
else if(data == midi_continue) {
play_flag = 1;
}
else if(data == midi_stop) {
play_flag = 0;
}
else if((data == midi_clock) && (play_flag == 1)) {
Sync();
}
}
}
void Sync() {
// do something for every MIDI Clock pulse when the sequencer is running
}
No.
0xfa, 0xfc and 0xfb are all controls for the current song being played. That is when playing a MIDI file.
Your code needs to concentrate on 0xf8, this is sent 24 times per quarter note when synchronization is required. You can use the time between these pulses to work out the BPM.
something like this?
byte midi_clock = 0xf8;
byte data;
void setup() {
Serial.begin(31250);
}
void loop() {
if (Serial.available() > 0) {
data = Serial.read();
if (data == midi_clock) {
Sync();
}
}
}
void Sync() {
// if midi_clock = true, power to led
// if midi_clock = false, no power to led
}
Well the Sync function is not going to do anything for you even if you turn the comments into code. the midi_code variable is not a boolean variable and so will not return a true or false.
You described what you wanted to do in the first post so why are you making no attempt to do it in the code?
Because I don’t know how to read 24 pulses or what to do with the reading, isn’t that already obvious from post 1?
There are many ways you can go about this, here is one way that springs to mind.
When you get one of these messages you set a unsigned long variable to the value in the system clock, and set an integer counter by using something like:-
startTime = millis();
beatCount = 1;
Then after that, each time you get another one, just increment the count until you have counted 24 * 4 = 96 messages. Then you can work out the time in milliseconds it takes for a whole note, by subtracting the startTime from the current millis() value, and dividing the result by 96.
sort of like this:-
// at the start of the code define these variables
unsigned long int startTime;
int beatCount;
bool counting = false;
long int bpm;
// then when you get a midi_clock message you use
if(data == midi_clock) {
if( not counting) { // first time you have seen a clock message in this batch
startTime = millis();
counting = true;
beatCount = 1;
}
else {
beatCount += 1;
if (beatCount >= 96) {
noteTime = (millis() - startTime) / 96;
counting = false;
// you now have the time for one note so calculate the BPM
bpm = (noteTime * 60) / 1000;
// now display the BPM - note you can't use Serial.print because the baud rate is set for MIDI.
}
}
}
Note the above has not been tested.
By changing the number of messages you count you can get half, quarter or eighth note times.
Think the bpm calc is more like: (if notetime is for 4 beats like youve done here)
noteTime = millis() - startTime;
bpm = 60*1000*4/notetime
// Or more simply,
bpm = 240000/notetime
I think noteTime would more correctly be called barTime (for 4/4 time anyway)
This works, it prints bpm to serial monitor
thanks for the help
#include <MIDI.h>
byte midi_clock = 0xf8;
unsigned long int startTime;
int beatCount;
bool counting = false;
long int bpm;
long int noteTime;
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
void setup() {
MIDI.begin(MIDI_CHANNEL_OMNI);
Serial.begin(57600);
Serial.println("MIDI Input Test");
}
void loop() {
if (MIDI.read()) { // Is there a MIDI message incoming ?
byte type = MIDI.getType();
if (type == midi_clock) {
if ( not counting) { // first time you have seen a clock message in this batch
startTime = millis();
counting = true;
beatCount = 1;
}
else {
beatCount += 1;
if (beatCount >= 96) {
noteTime = millis() - startTime;
counting = false;
// you now have the time for one note so calculate the BPM
bpm = 240000/noteTime;
// now display the BPM - note you can't use Serial.print because the baud rate is set for MIDI.
Serial.println(bpm);
}
}
}
}
}
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.