-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #335 from microsoft/pete-dev
Create mapping-midi1-port-concepts.md
- Loading branch information
Showing
1 changed file
with
72 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
--- | ||
layout: page | ||
title: Mapping MIDI 1.0 Ports | ||
parent: Transport Types | ||
grandparent: Windows MIDI Services | ||
has_children: false | ||
--- | ||
|
||
# Mapping MIDI 1.0 Ports to UMP Endpoints | ||
|
||
The big conceptual change between MIDI 1.0 and MIDI 2.0 / UMP (Universal MIDI Packet) endpoints is that the concept of a "Port" is no longer used. | ||
|
||
## Background | ||
|
||
In USB MIDI 1.0, messages are sent over USB using a 32-bit packet. That packet includes a virtual cable identifier, which is a number which maps to one of 16 possible virtual cables on the endpoint. This allows a single MIDI 1.0 device to have, for example, 8 input ports and 8 output ports on the single endpoint. | ||
|
||
MIDI 2.0 UMP has a similar concept, but the logical equivalent of that cable is a group. Because the group index is included in the message itself, and not in additional data sent to the device, all addressing required to route within an endpoint is included in the message. | ||
|
||
Additionally, some MIDI 2.0 UMP messages have no group information because they apply to the entire endpoint. For example, Endpoint Discovery messages, Function Block Info Notifications, and others. | ||
|
||
## How we approach this in Windows MIDI Services | ||
|
||
With Windows MIDI Services, we made the decision early on, validated by hardware and software partners, to provide a single unified view of an endpoint, whether it represents a MIDI 2.0 native endpoint or a collection of MIDI 1.0 cables on an endpoint. We also decided, because UMP was designed with this in mind and includes 1:1 mappings between MIDI 1.0 byte-format messages and their MIDI 1.0 Protocol in UMP equivalents, to present all MIDI 1.0 and MIDI 2.0 messages using a single format: UMP. | ||
|
||
> That means that Windows MIDI Services has no "ports". (We do map back to ports for our older MIDI 1.0 APIs, but that is for backwards compatibility with those APIs) | ||
### Cables to Groups | ||
|
||
When we enumerate a MIDI 1.0 USB device in the service, we create an aggregate endpoint for that device. As part of that, we build a map of UMP group indexes to MIDI 1.0 KS Pins. We use this for routing so when you address a specific Group. | ||
|
||
At the same time, we create virtual Group Terminal Blocks for that device. The names that normally show up as the port name in MIDI 1.0, now become the name of the group terminal. | ||
|
||
### Message listeners for MIDI 1.0 port-like access | ||
|
||
If your application is set up to deal more with single ports, we have an affordance in the SDK: the Message Listener. Anyone can build a message listener, but we supply ones to listen to one or more groups specifically for this use-case. This enables us to scale better by keeping only one connection to the endpoint, but filtering the messages on the client. | ||
|
||
Sending messages are still accomplished by communicating directly with the endpoint object, with an appropriate Group index in the message itself. | ||
|
||
## How to present this to your users | ||
|
||
In MIDI 2.0 and UMP, the addressible entities are the Endpoint, the Group, and the Channel. That information should always be made available in some way to your user. | ||
|
||
MIDI 2.0 devices typically support Function Blocks, which are named entities which can span one or more groups, and which can be moved at runtime, by design. Whenever possible, Function Blocks are preferred over Group Terminal Blocks. | ||
|
||
> The enumeration support in `MidiEndpointDeviceInformation` also supports projecting a Group Terminal Block (a USB concept) to its equivalent Function Block. So if Function Blocks are not available natively from the MIDI 2.0 device, you can still work with the same entity as projected from the Group Terminal Block. | ||
Group Terminal Blocks are only for USB devices, but they are also static. They do not change at runtime, but a device could potentially create different ones the next time it is created (most do not). | ||
|
||
So when presenting the information to your users, one possible format would be | ||
|
||
``` | ||
<Endpoint Name> | ||
- Group <Group Number> (<Group Terminal Block or Function Block Name which could change>) <Channel> | ||
- Group <Group Number> (<Group Terminal Block or Function Block Name which could change>) <Channel> | ||
- Group <Group Number> (<Group Terminal Block or Function Block Name which could change>) <Channel> | ||
``` | ||
|
||
An example would be | ||
|
||
``` | ||
Contoso Synth | ||
- Group 1 (Synth Engine) Channel 5 | ||
- Group 2 (Synth Engine) Channel 1 | ||
- Group 3 (Keyboard) Channel 1 | ||
``` | ||
|
||
Of course, how you present this to your users is up to you and the unique needs of your application. This is only one possible approach. | ||
|
||
> Note that Groups, like Channels, are 0-15 for the index, but 1-16 for the display value. The `MidiGroup` and `MidiChannel` types handle this for you automatically, if you use them. They also include the abbrviations for Group and Channel. | ||
It may take a little getting used to to work with the new endpoint approach, but this is designed for the future, so as more MIDI 2.0 native devices arrive on market, the approach will seem more natural. |