fbpx
Skip to main content

MIDI Forum

Midi Clock from Aud...
 
Notifications
Clear all

Midi Clock from Audio or Midi Notes?

22 Posts
4 Users
0 Reactions
15.5 K Views
Gabe
 Gabe
Posts: 5
Active Member
Topic starter
 

Hello guys,

I'm a guitarist and nub to using midi. I wonder if there is any way of generating or converting a midi clock from midi notes or events? I use a standalone audio multitrack player that can play a midi track in sync with the audio tracks but unfortunately can't provide midi clock. That would be great if I could sync time-based effects with my backing tracks. I found Midi solutions' Event processor plus but due to the lack of my midi knowledge i can't determine if i could use it for that... thanks in advance for any advice!

 
Posted : 22/03/2021 6:07 am
Bavi_H
Posts: 266
Reputable Member
 

I do not have a MIDI Solutions Event Processor, but I have looked at their free MIDI Solutions Programming Tools to get an idea what is possible with their products. It appears that it would be possible to convert a note message into a clock message:

Then you'd just have to create a MIDI file that has 24 notes per quarter note and it would get converted to the expected 24 clocks per quarter note.

I wonder, are you using a Cymatic device? I wish Cymatic could update their existing devices or release a new model that can send out MIDI clock, it seems like their users often want to do that.

Perhaps you have seen the previous midi.org forum posts from Cymatic device users discussing the possibility of embedding MIDI clocks in a MIDI file:

https://www.midi.org/forum/3769
https://www.midi.org/forum/1818

If you embed MIDI clocks in a MIDI file, the Cymatic LP16 will send them out, maybe other Cymatic devices will too? To embed MIDI clocks into a MIDI file, you might need to use a specific sequencer (like Sekaiju). You have to embed a MIDI clock inside of an esoteric F7 MIDI file event (called a "sysex continuation" or "escaped" or "sysex (arbitrary)" event).

I can see how converting a note into a clock might be easier to do albeit with the additional cost of purchasing an external converter like the MIDI Solutions Event Processor.

But if you want, you might consider the cheaper but more technically involved route of embedding clock messages into a MIDI file.

(Since this is the third time this has come up, I am going to look into writing some program or script that can generate a MIDI file with embedded clocks.)

 
Posted : 22/03/2021 8:43 am
Gabe
 Gabe
Posts: 5
Active Member
Topic starter
 

Thanks for your effort and comment! Yes, it's a Cymatic LP-16. The guys at Cymatic made a big mistake with this. I will check the posts you mentioned. Embedding midi clock sounds good. Of course I prefer the cheaper solution and the less device, but as I'm new to midi I don't know if I can make it work. I would appreciate it if you could do such a script so do all the LP-16 users.

 
Posted : 22/03/2021 10:55 am
Bavi_H
Posts: 266
Reputable Member
 

I created the attached HTML JavaScript page to generate a MIDI file that has MIDI clocks in it:

Download: clock-midi-file-generator.zip

Let me know if this kind of clock MIDI file works for you. This esoteric embedding of a MIDI clock in a MIDI file interests me, and I'm interested to know if it turns out to be useful in practice.

The generated MIDI file is set up to send the "F8" clock message the required 24 times per quarter note. But another user reported that their Cymatic LP-16 incorrectly sends "F7 F8" each time, and wondered if that was why some of their devices didn't work.

 
Posted : 23/03/2021 7:32 am
Gabe
 Gabe
Posts: 5
Active Member
Topic starter
 

Bavi_H, thank you so much for the effort you have put into this topic! I can try it on the weekend at the earliest. I’m very excited!

 
Posted : 23/03/2021 9:15 am
Gabe
 Gabe
Posts: 5
Active Member
Topic starter
 

Status report: I've just figured out how to add program changes and CC messages to the midi file generated by Bavi_H's script, because Ableton is not suitable for that, or I just can't handle it enough. So I used Sekaiju. I played the midi file with the LP-16 into a midi monitoring app and it seems ok. I can see all the PC, CC and the F8 messages. There are no F7s. I will test it tomorrow on a real device as well.

Another thing: I contacted Midi Solutions and as it turned out, they added the capability to their Footswitch Controller to enable it to respond to a Note-On message as a tap when operating in Tap Tempo mode, so in this mode the Footswitch Controller sends MIDI Timing Clock messages at a rate of 24 per quarter note. It’s good to know if syncing might not come up with embedding midi clock.

 
Posted : 26/03/2021 2:54 pm
Gabe
 Gabe
Posts: 5
Active Member
Topic starter
 

Finally I tried it with my Fractal AX8, works fine. 🙂 Thanks for your support Bavi_H!

 
Posted : 27/03/2021 2:10 am
Mahlon Houlihan
Posts: 2
New Member
 

I'm struggling with a similar problem. Certain Yamaha devices generate MIDI Clock for their own internal use--like rhythm machines--but also allow the user to select an external MIDI Clock to drive the device's rhythm machine. In my specific case, I'm using some 80's era Yamaha gear, specifically an HX-1 (Electone organ) and an MDR (Music Disk Recorder, 3½" floppy based). When an artist uses MDR to record a performance using the organ's rhythm machine at a set tempo, the MDR does not capture the F8s from the organ and write them to the file, only the tempo (in BPM) setting. For playback, the MDR first tells the keyboard to use an external synchronous source and the MDR hardware generates the F8s to drive the organ's rhythm machine while streaming the file's MIDI events. At the end of playback, a SysEx from the MDR tells the organ to return to using the organ's internal MIDI clock.

This makes sense given the imperfection that can arise from a tempo (in BPM) expressed as an integer and fractional rounding the occurs during recording compared to the higher resolution possible from ticks relating to microseconds. This drifting of timing is evident when you use (no offense intended) the Clock MIDI File Generator program above to create two files, each of 99 measures at 4/4 time, but one at Tempo 120 and the other at Tempo 123. The two files are identical (aside from the Set Tempo Meta-Event) and don't account for the rounding that occurs when calculating delta times. Both files send the F8s using a delta time of 5. At 120 the delta time is 5.208 and at 123 the delta time is 5.125.

My analysis leads me to conclude that Yamaha dealt with this issue by periodically adjusting to any inaccuracy that may have occurred due to rounding. At a convenient tempo like 125 BPM there should be no loss due to rounding. At 125, I *almost* always get F8s every 20 (decimal) ticks and in the rare cases when a 19 comes across, it's followed up shortly there after with a 21 which makes me wonder if it's checking itself against another onboard clock for accuracy. At BPMs not evenly divisible by 24, I see the same error-correcting occurring rather than a steady stream of a single delta time. At the end of x number of events, the accumulated delta times will be as close as possible to real time by having added back time lost from any truncation or rounding calculation.

Back to the 123BPM example: For exact timing, the delta times should be 5,5,5,5,5,5,5, 6 ,5,5,5,5,5,5,5, 6 ,5,5,5,5,5,5,5, 6, a sum of 123.

I admit to being a little "green" to all this, so please correct me if any of my assumptions are wrong. My goal is to achieve accurate playback of these recorded performances not from the MDR device, but my own program using the Windows MIDI stream APIs. I think I have no choice but to add my own F8 MIDI messages to the performance data (making sure there's an F8 every BPM/24 ticks) and hope the API can process them accurately. Regrettably, playback of the event data using the organ's clock for the rhythm machine points out the timing drift after a few measures.

 
Posted : 16/04/2021 7:45 am
Bavi_H
Posts: 266
Reputable Member
 

the MDR does not capture the F8s [...] and write them to the file [...]. For playback, [...] the MDR hardware generates the F8s [...] while streaming the file's MIDI events.

Recording MIDI clock messages into a MIDI file is not typical. The Clock MIDI File Generator is only intended as a possible workaround for devices that can play MIDI files but do not have the ability to generate MIDI clock messages in their MIDI output.

The behavior exhibited by your Yamaha Music Disk Recorder is the expected typical behavior. MIDI file recorders do not store MIDI clock messages in the MIDI file, but they might have an option to interpret incoming MIDI clock messages to determine the quarter note-based position that has elapsed or calculate the intended tempo. MIDI file players might have an option to generate MIDI clock messages at the MIDI file's current tempo value and mix them into the output.

when you use [...] the Clock MIDI File Generator program above to create two files [...] one at Tempo 120 and the other at Tempo 123[, t]he two files are identical (aside from the Set Tempo Meta-Event) [...]. Both files send the F8s using a delta time of 5.

The Clock MIDI File Generator generates MIDI files with a resolution of 120 ticks per quarter note.

When MIDI clock messages are used, they are sent at a rate of at 24 clocks per quarter note. Since the generated MIDI file resolution is 120 ticks per quarter note, this means the generated clocks are always 5 ticks apart, no matter what the tempo is.

The software that plays back the MIDI file is responsible for converting the quarter note-based ticks into absolute time-based seconds. To make that conversion, the playback software will use the tempo value stored in the MIDI file (microseconds per quarter note) to know how long each quarter note should be in seconds.

The Clock MIDI File Generator allows you to enter a tempo value in quarter notes per minute with any number of decimal places. It will store a value in the MIDI file in microseconds per quarter note that is the closest match to the tempo value you enter. This is the most precise tempo representation possible in a MIDI file.

 
Posted : 17/04/2021 5:16 am
Gabriele
Posts: 6
Active Member
 

Hi i try the script but is send out F7 before F8 so F8 is recognized as an argument of F7 (System Exclusive message). F8 is a realtime message and only need 0XF8 argument to be passed.

i tried to modify your script without success...any suggestions? Thanks

let clock_event_buffer = new ArrayBuffer(1);
let clock_event_array = new Uint8Array(clock_event_buffer);

clock_event_array[0] = 0xF8;

events_accumulator.push(clock_event_buffer);

 
Posted : 24/04/2021 12:41 pm
Bavi_H
Posts: 266
Reputable Member
 

Hi i try the script but is send out F7 before F8 [...]

i tried to modify your script without success...any suggestions?

Be aware that certain status bytes in a MIDI file have a different meaning than the same status bytes on a MIDI cable. (For example, F7.) Also be aware that some status bytes you can encounter on a MIDI cable are not allowed as status bytes in a MIDI file. (For example, F8.)

In a MIDI file, a status byte of F7 is used to store bytes that will be sent verbatim to the MIDI output port. The status byte of F7 itself is not supposed to be sent to the MIDI output port, just the data bytes of the message.

The code changes you described will put messages containing a single F8 in the generated MIDI file. Unfortunately, a message containing a single F8 isn't allowed in a MIDI file. Software or devices that try to handle a MIDI file like that could refuse to open the file or crash. Why? When you are reading a MIDI file, there are specific rules so you know how many bytes are part of each message at every point in the MIDI file. If you encounter a status byte of F8 in a MIDI file, there are no rules defined for how many bytes to expect next.

Storing MIDI clock messages into a MIDI file is not typical. The Clock MIDI File Generator is only intended as a possible workaround for devices that can play MIDI files but do not have the ability to generate MIDI clock messages in their MIDI output.

The only possible way to store a MIDI clock message in a MIDI file is to store it inside of an F7 message in a MIDI file. MIDI players are supposed to send the bytes stored in an F7 message directly to the MIDI output port. The status byte of F7 itself is not supposed to be sent to the MIDI output port.

When you play the generated MIDI file containing clock messages, if you are seeing incorrect "F7 F8" bytes getting sent, and if this causes your target device to ignore the F8 clock message, then you'll need to figure out some other way to generate a clock message.

Other people have had ideas to possibly purchase a device that will transform some simple MIDI message (like a note or a control change) into a clock message. But I don't know if anyone has tried that yet.

Earlier in this thread, Gabe reported "I contacted Midi Solutions and as it turned out, they added the capability to their Footswitch Controller to enable it to respond to a Note-On message as a tap when operating in Tap Tempo mode, so in this mode the Footswitch Controller sends MIDI Timing Clock messages at a rate of 24 per quarter note. It's good to know if syncing might not come up with embedding midi clock."

 
Posted : 24/04/2021 3:58 pm
Gabriele
Posts: 6
Active Member
 

Hi i try the script but is send out F7 before F8 [...]

i tried to modify your script without success...any suggestions?

Be aware that certain status bytes in a MIDI file have a different meaning than the same status bytes on a MIDI cable. (For example, F7.) Also be aware that some status bytes you can encounter on a MIDI cable are not allowed as status bytes in a MIDI file. (For example, F8.)

In a MIDI file, a status byte of F7 is used to store bytes that will be sent verbatim to the MIDI output port. The status byte of F7 itself is not supposed to be sent to the MIDI output port, just the data bytes of the message.

The code changes you described will put messages containing a single F8 in the generated MIDI file. Unfortunately, a message containing a single F8 isn't allowed in a MIDI file. Software or devices that try to handle a MIDI file like that could refuse to open the file or crash. Why? When you are reading a MIDI file, there are specific rules so you know how many bytes are part of each message at every point in the MIDI file. If you encounter a status byte of F8 in a MIDI file, there are no rules defined for how many bytes to expect next.

Storing MIDI clock messages into a MIDI file is not typical. The Clock MIDI File Generator is only intended as a possible workaround for devices that can play MIDI files but do not have the ability to generate MIDI clock messages in their MIDI output.

The only possible way to store a MIDI clock message in a MIDI file is to store it inside of an F7 message in a MIDI file. MIDI players are supposed to send the bytes stored in an F7 message directly to the MIDI output port. The status byte of F7 itself is not supposed to be sent to the MIDI output port.

When you play the generated MIDI file containing clock messages, if you are seeing incorrect "F7 F8" bytes getting sent, and if this causes your target device to ignore the F8 clock message, then you'll need to figure out some other way to generate a clock message.

Other people have had ideas to possibly purchase a device that will transform some simple MIDI message (like a note or a control change) into a clock message. But I don't know if anyone has tried that yet.

Earlier in this thread, Gabe reported "I contacted Midi Solutions and as it turned out, they added the capability to their Footswitch Controller to enable it to respond to a Note-On message as a tap when operating in Tap Tempo mode, so in this mode the Footswitch Controller sends MIDI Timing Clock messages at a rate of 24 per quarter note. It's good to know if syncing might not come up with embedding midi clock."

Ye i build myself, before studiing the SMF way, an arduino based tool that do the same as Midi Solution!! The box can translates notes into MIDI CLOCK, MIDI START, MIDI STOP and it works like a charm. But, u know, the idea of going direct from the cymatic to a midi device in more strong.

I try your script but my hardware (Moog sub 37) cannot sync to that...dunno why!!

Any idea or anyone had success with the code?

another thing. I noticed in your code wehn you parse the tempo that you add 0.5. It is right? and why? I mean the meta event will ever display wrong infos about bpm! If you set 81 bpm the meta event will say 80. I think is not a real probelm in the program cause the time is calculated in microseconds...but can u explain this to me? Thanks 🙂

Thanks!

 
Posted : 25/04/2021 6:58 am
Bavi_H
Posts: 266
Reputable Member
 

anyone had success with the code?

Earlier in this thread, Gabe said a generated MIDI file containing clock messages successfully got his Cymatic LP-16 to send clock messages to his Fractal AX8. Gabe reported his Cymatic LP-16 does not send the incorrect F7 bytes. (However, as I mentioned earlier in this thread, there is an older thread in which user Florent reported their Cymatic LP-16 does send the incorrect F7 bytes.)

Ye i build myself, before studiing the SMF way, an arduino based tool that do the same as Midi Solution!! The box can translates notes into MIDI CLOCK, MIDI START, MIDI STOP and it works like a charm. But, u know, the idea of going direct from the cymatic to a midi device in more strong.

Cool!

Does your Kiwi Lab MIDI Box send an FA start message before the F8 clock messages? Maybe your Moog Sub 37 requires an FA start message in order for its sync to work. The MIDI file generated by the Clock MIDI File Generator only contains F8 clock messages. The attached test modification to the Generator changes the first message to a start and a clock (FA F8).

Download: clock-midi-file-generator-v1.01-test.zip

Maybe updating your Moog Sub 37 firmware will help? In the Moog Sub 37 page Downloads section, the firmware zip file includes a PDF file with instructions and a list of changes introduced in each firmware version. I see the following changes to sync behavior in the list:

NEW IN 1.0.4
[...] Change in External Sync behavior: does not require MIDI Start message [...]

NEW IN 1.0.2
[...] MIDI sync behavior fixes and improvements

If your Kiwi Lab MIDI Box is only sending F8 messages and your Moog Sub 37 works with them, but your Cymatic device (is it a Cymatic LP-16?) playing a MIDI file generated by the Clock MIDI File Generator is sending "F7 F8" bytes and your Moog Sub 37 doesn't work with them, that would suggest the problem is the incorrectly sent F7 bytes. Unfortunately, I don't think there's a way to get your Cymatic device to stop sending the incorrect F7 bytes by changing the MIDI file.

 
Posted : 25/04/2021 12:28 pm
Bavi_H
Posts: 266
Reputable Member
 

I noticed in your code wehn you parse the tempo that you add 0.5. It is right? and why?

In JavaScript, parseInt ignores everything after the decimal point:

parseInt(1.1) // returns: 1
parseInt(1.9) // returns: 1

I want to round to the nearest integer, so I add .5:

parseInt(1.1 + .5) // returns: 1
parseInt(1.9 + .5) // returns: 2

To be more clear, maybe I should use Math.round(x) instead of parseInt(x + .5). I don't remember why I got in the habit of using parseInt(x + .5).

For example, 81 quarter notes per minute is exactly 740740.740... microseconds per quarter note. I round that to 740741 microseconds per quarter note because that's the closest value to the exact value that is possible to store in a MIDI file:

A: microseconds per quarter note
B: offset from 740740.740... microseconds per quarter note
C: quarter notes per minute
D: offset from 81 quarter notes per minute

A B C D
740740 ≈-0.741 ≈81.000081 ≈+0.000081
740741 ≈+0.259 ≈80.999972 ≈-0.000028

If you set 81 bpm the meta event will say 80.

740741 microseconds per quarter note is exactly 80.99997165... quarter notes per minute. If you are seeing that show up as "80", then it sounds like your display device is ignoring everything after the decimal point. It would be better to do something like round the value to 2 decimal places.

 
Posted : 25/04/2021 1:14 pm
Gabriele
Posts: 6
Active Member
 

Does your Kiwi Lab MIDI Box send an FA start message before the F8 clock messages? Maybe your Moog Sub 37 requires an FA start message in order for its sync to work. The MIDI file generated by the Clock MIDI File Generator only contains F8 clock messages. The attached test modification to the Generator changes the first message to a start and a clock (FA F8).

Ye The "Kiki Lab" also send start and stop message. The Sub37 not need the start to sync but need it in you want to make sure that that if you stop and in a point of a song (may be @ reharsal) that is not properly the quarter note, it goes out of sync so i wrote the code to send start and stop so i'm sure that every time the sequence stops or the song end the moog is in STOP and before sending F8 to set to START. This way he is in lock in every situation.

I manage to modify your script to send start message before reading you comment 🙂

Why u send a bit of F8 before the start? I mean a modified the code this way...it is correct?

[code type=markup]
/* MIDI START */

let start_event_buffer = new ArrayBuffer(4);
let start_event_array = new Uint8Array(start_event_buffer);

start_event_array[0] = 0; // delta time 0
start_event_array[1] = 0xF7;
start_event_array[2] = 1;
start_event_array[3] = 0xFA;

events_accumulator.push(start_event_buffer);

/* ... First clock event at time zero: */

let delta_zero_buffer = new ArrayBuffer(1); // one byte of value zero

events_accumulator.push(delta_zero_buffer);

let clock_event_buffer = new ArrayBuffer(3);
let clock_event_array = new Uint8Array(clock_event_buffer);

clock_event_array[0] = 0xF7;
clock_event_array[1] = 1;
clock_event_array[2] = 0xF8;

events_accumulator.push(clock_event_buffer);

/* ... Repeating clock events: */

let ticks_per_clock = ticks_per_q / 24;
let variable_length_quantity_stack = new Array();

for(let i = 0, remainder = ticks_per_clock; (i 0); ++i, remainder >>= 7)
{
variable_length_quantity_stack.push(remainder & 0x7F);
}

let delta_size = variable_length_quantity_stack.length;
let delta_buffer = new ArrayBuffer(delta_size);
let delta_array = new Uint8Array(delta_buffer);

for(let i = 0; i < delta_size - 1; ++i)
{
delta_array = 0x80 | variable_length_quantity_stack.pop();
}

delta_array[delta_size - 1] = variable_length_quantity_stack.pop();

let clocks_per_measure = clocks_per_time_sig_bottom * time_sig_top;
let measures = parseInt(document.getElementById("measures").value, 10);
let total_clocks = clocks_per_measure * measures;

for(let i = 0; i < total_clocks; ++i)
{
events_accumulator.push(delta_buffer);
events_accumulator.push(clock_event_buffer);
}

/* MIDI STOP */

let stop_event_buffer = new ArrayBuffer(4);
let stop_event_array = new Uint8Array(stop_event_buffer);

stop_event_array[0] = 0; // delta time 0
stop_event_array[1] = 0xF7;
stop_event_array[2] = 1;
stop_event_array[3] = 0xFC;

events_accumulator.push(stop_event_buffer);
[/code]

Also there is another problem. If i want to have on the same midi file all my cc and pc i have found only a not easy way to do it...maybe you can suggest me something more smart...i explain...

Midi clock generated file -> Cubase -> Add pc cc etc...

At this point cubase recognize all the sysex msg in proper timeing position but he assume they are Sysexmessage so he automaticcaly trasform very F7 F8 in F0 F7 where in between u can put a varible...but we cannot input 248 (F8) as the argument of a sysex message is max 127 (dec.) Same problem in logic.

So after addiig all my stuff and saved the file i had to open it in an hez editor and batch replace al F0 with F7, all F7 wi F8 and the firts to FA and the last to FC. Works but is a little bit tricky 🙂 Any idea?

About the timing...u right, i do my homework too and i arrived at the same conclusion...but 80 instead of 81 show on the programm is only a display issue, the real midi tempo will still be 89.9999... so no problem (if you don't play a song of 20min) right?

 
Posted : 25/04/2021 3:59 pm
Page 1 / 2
Share: