Skip to content
This repository has been archived by the owner on Jan 2, 2018. It is now read-only.

sequencePosition in midiMessage #1

Open
notator opened this issue May 3, 2012 · 8 comments
Open

sequencePosition in midiMessage #1

notator opened this issue May 3, 2012 · 8 comments

Comments

@notator
Copy link

notator commented May 3, 2012

At line 82 of random-sequence.js
midiMessage = midiAccess.createMIDIMessage(midiBridge.NOTE_ON, 0, noteNumber, velocity, sequencePosition);
you pass sequencePosition as the 5th argument.
As far as I can see, this parameter is only used by midiMessage.toString(), and is not recoverable in Javascript as (for example)
var sequencePosition = midiMessage.sequencePosition;

The caller of midiAccess.createMIDIMessage(...) can keep track of the message's sequencePosition separately if necessary, so I'm wondering if the midiMessage could be made smaller by omitting its internal sequencePosition field.

Maybe I'm being over-sensitive about the size of midiMessages, but I want to create all of them for a particular piece of music before sending them to the output device. That could mean a very large number of messages to be held in memory at the same time...

best, j

@abudaan
Copy link
Owner

abudaan commented May 3, 2012

I have asked Jussi's opinion on this issue as well, and he said that for sequencer purposes it is simpler to couple timestamp and message.

In Java MIDIMessages don't have a timestamp, but MIDIEvents do. The benefit of this could be that you can send several MIDIMessages with the same timestamp in a single event. However in Java an event is sent for every message.

In Jussi's proposal for the MIDI event listener, an event has an array of messages, so it can deliver several messages at once.

Anyway, I think this topic needs some more discussion.

@notator
Copy link
Author

notator commented May 3, 2012

I'm going to be writing my own track-like data structures, which are singly-linked queues of MIDIEvent nodes. Each MIDIEvent node has a (millisecond) position re the beginning of the performance, and a singly-linked queue of logically synchronous MIDIMessages. I wont be using/setting MidiBridge's MIDIMessage.timeStamps.

Apropos MIDIEvents:
I'm a bit worried about sending their "synchronous" MIDIMessages "as fast as possible" to the output device.
In my experience (for example in Quicktime) it can take some time for the device to react to a patch change command. If one sends Quicktime a patch-change command immediately followed by a NOTEON, the patch change can take effect after the NOTEON (!). Is that actually forbidden by the MIDI standard? Are there any guidelines I should know about? Or is Quicktime just not very good at implementing the MIDI Standard?

In other words: According to the MIDI Standard, do MIDIEvents containing control information have to precede MIDIEvents containing NOTE_ONs by a minimum amount of time in order to take effect?

And another thing: You use microseconds for the timeStamps. This would seem to mean that MIDIMessages arriving from one of my MIDIEvents could be being given different timeStamps than the milliseconds I'm using to order my "tracks". It might actually be wrong or meaningless for me to set the timeStamp just by multiplying by 1000.

best, j

@notator
Copy link
Author

notator commented May 4, 2012

In the above scenario, I could theoretically set the (microsecond) MIDIMessage.timeStamp at the time the message is actually sent. But a) I cant find a timer which is accurate to microseconds on my computer, and b) I dont think the output device ever needs that info.

best, j

@abudaan
Copy link
Owner

abudaan commented May 6, 2012

If you handle the timing of sending MIDI messages in Javascript, you
don't need to add a timestamp to the messages.

Timing in Javascript is done in milliseconds, so all messages will be
'quantized' to millisecond values.

On 05/04/2012 10:20, James Ingram wrote:

In the above scenario, I could theoretically set the (microsecond) MIDIMessage.timeStamp at the time the message is actually sent. But a) I cant find a timer which is accurate to microseconds on my computer, and b) I dont think the output device ever needs that info.

best, j


Reply to this email directly or view it on GitHub:
#1 (comment)

@notator
Copy link
Author

notator commented May 6, 2012

Yes, that's what I'm doing. So you can remove the microsecond timeStamp from MIDIBridge altogether, right?
Milliseconds are quite accurate enough for MIDI. :-)
best, j

@abudaan
Copy link
Owner

abudaan commented May 6, 2012

No, timestamps are quite useful, for instance if you want be able to show the progress of a MIDI file while playing back, or use a slider to allow the user to jump to a certain part in the MIDI file.

For very subtle timing you will find that milliseconds are too coarse.

On 05/06/2012 15:20, James Ingram wrote:

Yes, that's what I'm doing. So you can remove the microsecond timeStamp from MIDIBridge altogether, right?
Milliseconds are quite accurate enough for MIDI. :-)
best, j


Reply to this email directly or view it on GitHub:
#1 (comment)

@notator
Copy link
Author

notator commented May 6, 2012

You may well be right. :-) Please bear with me. I'm trying to understand this better.

I just took a look at a discussion about Synching Sequence Playback in the reference documents I'm using. Microseconds are the (integral) unit of measurement used for MIDIClock events. So one can use microseconds when tracking MIDIClocks.

But I don't really understand why you need to use the MIDIClock's microsecond duration. Why not just track the MIDIClock events themselves? That seems to be what MIDI is expecting us to do -- and it would certainly simplify/speed up the arithmetic.
Setting a device's MIDIClock duration is done by setting a "tempo", not by using a microsecond value, and MIDIClocks are usually many thousands of microseconds long.
For example, the docs say: "if a master is set to a tempo of 120 BPM (ie, there are 120 quarter notes in every minute), the master sends a MIDI clock every 20833 microseconds."

Are there any other uses for microseconds? I'm trying to avoid them, because my computer seems to have no idea what they are. MIDI devices are something else.

Sorry if I'm being dense.

All the best,
James

@notator
Copy link
Author

notator commented Jun 6, 2012

I've just had a very interesting exchange with Chris Wilson and Jussi Kalliokoski in the following thread:
http://lists.w3.org/Archives/Public/public-audio/2012AprJun/0522.html

It is very important to realise that the last argument in line 82 of random-sequence.js:
midiMessage = midiAccess.createMIDIMessage(midiBridge.NOTE_ON, 0, noteNumber, velocity, sequencePosition);
is actually a time-stamp which can be used in Javascript to set the time at which the message will be sent. The thing that got me a bit confused was that it is called sequencePosition in the above call.

The point of this timestamp is not its apparent accuracy (that the value is in microseconds is a small detail) but that one can use it instead of using Javascript's setTimeout() or setInterval() methods to set the time at which messages should be sent.

setTimeout() and setInterval() are unreliable:
According to the W3C standard, the delay set in setTimeout() will never be less than 4 milliseconds. See
http://dev.w3.org/html5/spec-LC/timers.html.
In practice, the lower limit for the delay in setTimeout() can be much larger: "Timeout of 1 (or even 0 milliseconds) will actually become more than that... [snip]. In Internet Explorer, for example, the shortest clock tick is 15 milliseconds." [Javascript Patterns, first edition 2010, p.189 (Stoyan Stefanov, O'Reilly)]

The time interval in setInterval() is measured in milliseconds, so there are limits on the rates at which it can be used to send MIDI Clock events. (MIDI defines the rate at which MIDI Clocks are sent in microseconds. MIDI-Clocks are usually sent event every 20 milliseconds or so.)

All the best,
James

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants