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

Determine if hardware supports general MIDI instruments. #110

Open ghost opened 9 years ago

ghost commented 9 years ago

The situation - Someone develops a web component that is designed to play general MIDI music/sequences, possibly for use by games or as a standalone music player.

The problem - There is currently no way to determine if a MIDIOutput device provides a general MIDI instrument set, and that means end-users will have to select a usable device from a list.

For removable MIDI hardware this will probably always be a problem but modern sound cards typically provide a general MIDI instrument set. So, would it be possible for the MIDIOutput interface to expose a boolean flag that indicates if the device it represents is removable?

interface MIDIOutput : MIDIPort {
    readonly attribute bool removable; // indicates if the device is removable
    void send (sequence<octet> data, optional double timestamp);
};

Is this even possible to determine when scanning the hardware for available output devices?

bome commented 9 years ago

Applying such heuristics is usually a safe way to frustrate your users. If you attach an expensive "removable" GM synthesizer to the computer, they'll most likely want to use that. Conversely, on Windows, the built-in synth is not a lot of fun.

So, if you need to know if a port supports GM, then the flag should be bool supports_gm1 or so. USB-MIDI does provide an internal descriptor with flags for GM1, GM2, XG and GS support. CoreMIDI has a flag kMIDIPropertySupportsGeneralMIDI. On Windows, I don't think it's possible to find out (except for the built-in synth).

Regarding a removable flag, I'd rather not have it in the API. It is not always possible to find out 100% if a port is removable, and you'd need to exactly need to define what "removable" means. Is a built-in 5-pin DIN port removable? Is a synth removable if it is internally attached via USB? Conversely, if removable is not set for a port, does that mean that it is not removable or that it was just not possible to find out if it is removable? How do virtual MIDI ports fit?

For me, it's not such a bad idea to let the users select the preferred port (and remember that port).

ghost commented 9 years ago

Understood, but I still think the API should provide some indication of GM support. Popping onto YouTube and having to manually select the audio/video decoding hardware to use wouldn't be a very nice user experience. That would never happen or course but it's the situation that users will currently find themselves in whenever they hit a Web MIDI enabled website or application.

Remembering ports is fine during a single session but one or more devices could be rearranged or removed while the website or application isn't being used, i.e. while it's unable to track the ports, so I'm not sure how viable that solution would be in the real world.

As developers I guess we could maintain our own lists of GM compatible devices but there are so many devices available that it would make maintaining those lists very unpleasant.

cwilso commented 9 years ago

I'm not convinced a flakily-supported "supportsGeneralMIDI" flag is a good idea. (For context - there's no way to definitively tell if GM is supported in a synth (e.g. a req/resp ping in sysex would have been great, but doesn't exist in GM). USB MIDI class definition does define an element capability for GM - but defines GM, GM1, GS, XG, DLS1, DLS2 and other bits that might be interesting. I think we should either have a more general examination of these, or not take this on in v1. Thoughts from others?

(if we did this, it would need to be available to set on virtual ports when virtual ports are exposed.)

bome commented 9 years ago

I agree with Chris. A general facility for properties or flags would be nice, but not essential. However, if there is such a facility, each flag should be one of: "supported", "not supported", or "unknown".

ghost commented 9 years ago

I have no idea how device detection is dealt with behind the scenes, so this might be a stupid question, but would it be safe to assume the first output device in the list (available immediately after a successful MIDI access request) would be the the user's primary audio device, e.g. a built-in soundcard?

If that behaviour is predictable then it may reduce (but not eradicate) the need for GM flags.

I'm only asking because that's the behaviour I'm seeing with my current hardware configuration.

bome commented 9 years ago

From my experience, that's a very unsafe bet. On Windows, the first MIDI out port is usually the built-in software synth (if there is a soundcard for audio). It has a GM2 soundset, but not high quality, and it has terrible latency. But Windows has the concept of a default MIDI device (MIDI Mapper), so using that device as default for playing back MIDI is probably the best idea. The user can choose the default MIDI port. I don't think that WebMIDI exposes which device is the default device, but maybe a good convention would be to order that device first.

OS X ships with a DLS synth, but it is not exposed as a MIDI port by default. On Linux, you need to install a soft synth like fluidsynth.

I don't think that the assumption that a built-in soundcard will have a synth is practical. Most computers just ship with cheap audio hardware without a hardware MIDI synth.

To my experience, the order of devices is rather random (usually reflects the order of insertion or driver initialization).

cwilso commented 9 years ago

OSX no longer ships with a software synth, I think.

Unfortunately, there are no ways to confirm that any given synth is a GM synth - for example, the default synths in Windows and OSX (in the past) do not have input ports back in to the system - i.e. they have no way to communicate back to the device - and the identifiers in the MIDI systems in those OSes do not identify them as GM devices.

The only way I could see this working is something akin to the Windows MIDI device mapper - that is, a user could select their "preferred GM synth" and we could give an explicit bit somewhere in the API to return the preferred GM output device. I don't think this scenario is that incredibly compelling today, though - vs the user simply selecting their preferred output device from a dropdown, and the software remembering it; and probably even defaulting to their only, or first, output device. I think this should be won't-fixed.

joeberkovitz commented 9 years ago

I agree with @cwilso that this is not a worthwhile thing to attempt in the API. Furthermore if people truly want a "safe" GM file playback option, they can now package a shrink-wrapped Web Audio-based MIDI player in their application rather than relying on finding a GM-compatible external softsynth or device.

ghost commented 9 years ago

A Web Audio based General MIDI player might be viable with a lot of work and the help of audio workers, when they eventually appear, but it would still be a challenge to optimize it for real world use.

I do understand why this feature request is a non mover tho, so feel free to close this one.

MidiHax commented 9 years ago

I'm inclined to won't-fix. There are few, if any, solutions that can be accomplished purely within the API and trying to solve the external standardization problems is probably not helpful at this point.

agoode commented 9 years ago

There are extra properties that are not being exposed that we could expose, which could give some extra information about the ports. On all of Mac, Windows, and Linux there are flags and things that give this information. I think having a feature request for a future version of Web MIDI to support properties would be ok.

For reference: https://msdn.microsoft.com/en-us/library/dd798451(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/dd798467(v=vs.85).aspx https://developer.apple.com/library/ios/documentation/CoreMidi/Reference/MIDIServices_Reference/#//apple_ref/doc/constant_group/Global_Constants http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html#ga0f89faac8be715b9e2d9d885c7f644a0

toyoshim commented 9 years ago

Here is one Web Audio based GM compatible synth. http://www.g200kg.com/webmidilink/gmplayer/ (See http://www.g200kg.com/en/docs/webmidilink/ for WebMidiLink).

For playing back SMF files for GM, it would be better to use platform independent synth like this rather than OS dependent synth that may generate different sound on each platform. Also, using native software synth raises security concerns. I am not happy to allow accessing software synth without any extra permission by default.

MidiHax commented 9 years ago

@agoode I think exposing the device properties is probably worthwhile as a non-essential feature but there are definitately some caveats. I'm not sure it is possible to abstract those into something platform-independent since each OS exposes a different set of properties. At best, they would have to be selectively available depending on the platform and that will cause confusion/irritation with developers expecting flag X to be populated when it's not available on platform Y. Additionally, the values of these flags are not always accurate and/or open to interpretation. Specifically, physical/virtual port devices that have no information about what is connected to them will be unable to accurately set some of these flags' values - again causing confusion.

cwilso commented 9 years ago

@agoode It's true that CoreMIDI has kMIDIPropertySupportsGeneralMIDI, and ALSA has SND_SEQ_PORT_TYPE_MIDI_GM. However, Windows doesn't expose this, IIUC; unless it's in the new Windows 8.1 APIs.

If we want to do this, we should do it based on USB-MIDI's element descriptor (http://www.usb.org/developers/docs/devclass_docs/midi10.pdf, page 23), and map other systems to that (since it's the underlying baseline for most devices). It's still not going to work in a number of cases (my MIDIMan hardware interface plugged in to my Yamaha QY70, e.g.).

I envision some kind of "capabilities" bag that exposes bits like "GeneralMIDI", "XG", "MTC", etc.

@toyoshim if there's a native software synth installed, it's going to be accessible without prompting by default, ne c'est pas?

toyoshim commented 9 years ago

@cwilso For Chrome/Windows, that's partially true for now. But for Chrome/other platforms, that's false. For Chrome/OS X, If IAC driver is enabled, software synths can be accessible via IAC ports, but a user should enable it manually AYOR.

For Chrome, running third party's native code in browser process is very scared. The number of visible software synths for Windows is countable. I know only three, OS providing GM compatible, VSC-88, and WinGroove. I should double check on this, but I believe Chrome/Windows does not support DXi. That's why I said partially. I'll ask an engineer who implements Windows port.

agoode commented 9 years ago

@cwilso Yes, the USB element descriptors are the best thing to use. Sadly ALSA currently has this in usb/midi.c: /* TODO: read port flags from descriptors */ :cry:

But it has a large list of hardcoded MIDI devices, so it's got that going for it.

cwilso commented 9 years ago

@toyoshim The Apple DLSMusicDevice was what I was referring to, not setting up an IAC device. I don't think that forces native code to run in the browser. According to Tom White, Windows desktop still ships with a pre-installed GM synth (as a MIDI device).

notator commented 9 years ago

Windows still ships with a pre-installed GM synth, but it seems to have moved in Windows 8 to become the first device in the device list instead of the second. See Faq 11 (bottom of page) at http://coolsoft.altervista.org/en/virtualmidisynth/faq

The MS GM synth is not showing up on my Windows 8 laptop - either in the Chrome MIDI implementation, or in Jazz (Firefox). It shows up fine in Windows 7 on another computer. I think that both Chrome MIDI and Jazz are probably looking for the synth in the same place on all Windows versions...

toyoshim commented 9 years ago

Chrome just uses aka winmm to control MIDI devices under Windows. I guess the GM synth is not exposed to the API any more, and DXi support is needed to use it.

notator commented 9 years ago

Its very strange. I am told that the MS GS Synth is showing up on other Windows 8.1 machines. I've posted a fuller summary of the situation and a question at [1] but have not had any reply. All the more reason to decrease our reliance on synthesizers supplied by operating systems. See #124.

[1]http://answers.microsoft.com/en-us/windows/forum/windows8_1-hardware/how-can-i-access-the-microsoft-gs-wavetable-synth/85219c03-75a5-4f63-b0ba-7a99f68d1300?tm=1427376560009

cwilso commented 8 years ago

I think the resolution was 'some kind of "capabilities" bag that exposes bits like "GeneralMIDI", "XG", "MTC", etc.', but I want to check.

notator commented 8 years ago

The above comments relating to the Windows synth are now obsolete. It has been banned since they were made.

This issue is originally asking for the MIDIOutput interface to include a 'removable' flag.

I'm soon going to be proposing some extensions to the MIDIOutput interface that are needed for software synths. If the flag gets added to the MIDIOutput interface, then it will always be true for software synths. If the host app sets a software synth to null or undefined, it can be GCed.