WebAudio / web-midi-api

The Web MIDI API, developed by the W3C Audio WG
http://webaudio.github.io/web-midi-api/
Other
323 stars 49 forks source link

Running Status #109

Closed ghost closed 9 years ago

ghost commented 9 years ago

The more I use Web MIDI and MIDI files the more important support for running status appears to be from an optimization and/or performance point of view.

dictionary MIDIOptions {
    boolean sysex = false;
    boolean runningStatus = false;
};

As far as I can work out, a Web MIDI implementation would only need to be able to detect hardware support for running status (or at least permit the use or running status and allow users to deal with the consequences when hardware doesn't support it), but it wouldn't need to concern itself with running status beyond that due to the low-level nature of the Web MIDI API.

Preventing the use of running status because hardware (or more likely the OS layer) might not support it seems like a restrictive approach to me, all things considered.

bome commented 9 years ago

Running status is an integral part of the MIDI protocol. Every (receiving) MIDI hardware must support it. So I don't understand why there would be the need for a MIDIOption runningStatus. In software API's, it is useful to always undo running status before it's passed to the application (sort of a normalization). The bandwidth savings do not play a role in software. Passing running status messages to an application seems counterproductive to me.

For the sending side, such a MIDIOption could be used to give a hint to the underlying MIDI subsystem to use running status when sending. But for me, it's OK to leave it up to the MIDI hardware to compress outgoing messages using running status or not. E.g. on 5-pin DIN, it will always make sense, but for USB transports it might not be necessary.

Let alone the problem that such an option might not be implementable because common OS MIDI API's do not give control over running status usage.

ghost commented 9 years ago

Web MIDI currently doesn't allow the sending of running status messages. I'm simply asking for this to be allowed if the OS layer supports it (which could be indicated by a flag in the Web MIDI API if needed).

agoode commented 9 years ago

This seems like a reasonable feature request.

bome commented 9 years ago

ah, I get it. One issue of running status is that you cannot easily merge multiple MIDI senders if they use running status, especially with multi-threaded usage, or when sending e.g. multiple tracks of a MIDI file (SMF). So effectively, allowing running status will put the burden on the users of the Web MIDI API to ensure that the running status messages they're sending don't conflict. I'd say it's much easier and safer to always let users undo running status before sending via WebMIDI (e.g. when reading SMF tracks).

Apart from the implementation aspect, do you have any evidence about potential performance gains? I cannot think of any...

toyoshim commented 9 years ago

If this is really needed, I prefer Web MIDI just allow it by default. Flag isn't needed. But, I don't think running status is useful any more. It was a kind of an optimization on a physical layer, especially for the original DIN. In the old days, the optimization were just exposed to applications directly. But it should not be done in modern APIs. There is no benefit except for making SMF decoding easier, but it just makes the API design complicated.

Inside Web MIDI implementation, a browser need to multiplex multiple inputs from each MIDIAccess client. So anyway, running status will be decoded internally, and pass it to the OS as a decoded sequence. If running status is really useful, the OS or a driver will encode it again internally even if application does not use running status at all. This optimization can be done transparently and we do not need to expose it to applications unless it makes a priceless benefit like a big performance gain.

ghost commented 9 years ago

If an implementation cannot deal with running status due to the way the API is designed then that's fair enough. Allowing running status isn't important per se it's just something that would be nice to have available considering it's part of the MIDI spec and supported by most hardware. It would also help to reduce the amount of data that needs to be stored in memory for large multi-track MIDI sequences.

jussi-kalliokoski commented 9 years ago

This is a duplicate of #24.

ghost commented 9 years ago

This is a counteraction not a duplicate, but it's becoming clear that running status isn't actually possible which seems incredibly odd considering it's part of the MIDI spec.

toyoshim commented 9 years ago

Oh, there was a deep discussion. That's a good reference. Thank you, Jussi.

cwilso commented 9 years ago

This issue is not a counteraction of #24, it's a disagreement with that issue. Regardless, I'd rather just deal with this here.

I have yet to hear a compelling reason to disagree with the resolution that Web MIDI will not expose or consume running status in its APIs, so I am inclined to close this. I think there may be some misunderstanding of what it means to "support running status".

1) If you have a synthesizer connected via a 5-pin DIN port that produces running status, it will still work with Web MIDI; the Web MIDI input listener will simply get unrolled (full 3-byte) messages.

2) Other MIDI APIs I've investigated (Windows MIDI, CoreMIDI, etc) do not expose running-status-encoded messages on input. CoreMIDI specifically disallows it in PacketLists ("Running status is not permitted.", from https://developer.apple.com/library/ios/documentation/CoreMidi/Reference/MIDIServices_Reference/index.html#//apple_ref/doc/uid/TP40010316-CHMIDIServiceshFunctions-SW8), which means input will have running status already decoded (and sending data cannot have running status); Windows MIDI will unroll it on input ("MIDI messages received from a MIDI input port have running status disabled; each message is expanded to include the MIDI status byte.", from http://msdn.microsoft.com/en-us/library/dd757284(v=vs.85).aspx).

3) Windows DOES enable send-encoding of running status: midiOutShortMsg() can just put in two bytes ("The two MIDI data bytes are optional, depending on the MIDI status byte. When a series of messages have the same status byte, the status byte can be omitted from messages after the first one in the series, creating a running status. Pack a message for running status as follows...", from http://msdn.microsoft.com/en-us/library/dd798481(v=VS.85).aspx). This is the only thing Web MIDI does not enable; you can't hand running-status-encoded data to MIDIOutput.send(). (CoreMIDI, as stated above, does not enable this.)

4) HOWEVER, by far the most common transport today is USB-MIDI - and USB-MIDI does NOT enable running status in its data transport. ("It also makes parsing MIDI events easier by packetizing the separate bytes of a MIDI event into one parsed USB-MIDI event. ... The remaining three bytes contain the actual MIDI event.", from http://www.usb.org/developers/docs/devclass_docs/midi10.pdf, page 16.) So even if you're using Windows MIDI to send messages, and using running status, it's getting re-expanded in the USB transport.

5) It is possible that a USB-MIDI-to-5-pin-DIN interface would re-encode running status in data being sent to a hardware 5-pin-DIN synthesizer (which MUST support it) - to optimize the use of that slow transport - but that is entirely out of our control, and not indicated in any way by the USB interface. Obviously, this would make no sense for a USB-MIDI-interface instrument (e.g. a synthesizer with a USB port), since it's not going over that 31.25kb transport.

In short: A) It makes the most sense to me (and clearly, to the designers of Windows MIDI and CoreMIDI) to NOT force Web MIDI developers to unroll running status in their own parsing; we need to mark timing of each individual message anyway. So we should unroll running status if for some reason we were to receive it (I'm not sure how we would, given our underlying transports don't give it to us).

B) I don't see any compelling reason for supporting OUTPUT of running status, either - we could enable it in MIDIOutput.send(), but in most APIs underneath us the Web MIDI implementation would need to immediately unroll it before sending it on, and even on any API that doesn't require unrolling running status, any USB-MIDI transports are going to need unroll it anyway.

Given these reasons, I simply don't see the reason for supporting sending of running status-encoded data; the only reason you might have running status already encoded would be in a Standard MIDI File, but even then the messages will not be packed in a way that makes this helpful (as they're interspersed with delta-times). Pre-encoding your own data as running status simply isn't an optimization that I can see.

If you think this is important for some reason, please explain the scenario that is disabled or harmed by not allowing sending running-status-encoded data, given the context above. I do not believe this is a real-world performance win; in fact, I think it's just going to result in data being decoded and encoded repeatedly to no benefit.

ghost commented 9 years ago

You have made some good points Chris, and it appears the decision to not support running status in Web MIDI was made a while ago, so I'm closing this issue myself and I apologize for bringing the subject to the foreground again.