- MIDI MIDI
- Перечисление MIDI-устройств Enumerate MIDI devices
- Создание вспомогательного класса для наблюдателя устройств Create a device watcher helper class
- Создание портов MIDI для отправки и получения сообщений Create MIDI ports to send and receive messages
- Использование встроенного в Windows синтезатора General MIDI Using the built-in Windows General MIDI synth
MIDI MIDI
В этой статье показано, как перечислять MIDI-устройства (Musical Instrument Digital Interface), а также отправлять и получать сообщения MIDI из универсального приложения для Windows. This article shows you how to enumerate MIDI (Musical Instrument Digital Interface) devices and send and receive MIDI messages from a Universal Windows app. Windows 10 поддерживает MIDI через USB (совместимые с классами и самые частные драйверы), MIDI через Bluetooth LE (годовщина Windows 10 и более поздние версии) и через свободно распространяемые сторонние продукты, MIDI через Ethernet и маршрутизацию MIDI. Windows 10 supports MIDI over USB (class-compliant and most proprietary drivers), MIDI over Bluetooth LE (Windows 10 Anniversary Edition and later), and through freely-available third-party products, MIDI over Ethernet and routed MIDI.
Перечисление MIDI-устройств Enumerate MIDI devices
Перед перечислением и использованием MIDI-устройств добавьте в свой проект следующие пространства имен. Before enumerating and using MIDI devices, add the following namespaces to your project.
Добавьте на свою XAML-страницу элемент управления ListBox, который позволит пользователю выбрать одно из подключенных к системе устройств ввода MIDI. Add a ListBox control to your XAML page that will allow the user to select one of the MIDI input devices attached to the system. Добавьте другой элемент управления для списка устройств вывода MIDI. Add another one to list the MIDI output devices.
Класс DeviceInformation метода FindAllAsync используется для перечисления различных типов устройств, обнаруженных Windows. The FindAllAsync method DeviceInformation class is used to enumerate many different types of devices that are recognized by Windows. Чтобы указать, что вам требуется только метод для поиска устройств ввода MIDI, используйте строку селектора, возвращенную MidiInPort.GetDeviceSelector. To specify that you only want the method to find MIDI input devices, use the selector string returned by MidiInPort.GetDeviceSelector. FindAllAsync возвращает коллекцию DeviceInformationCollection, которая содержит DeviceInformation для всех зарегистрированных в системе устройств ввода MIDI. FindAllAsync returns a DeviceInformationCollection that contains a DeviceInformation for each MIDI input device registered with the system. Если возвращаемая коллекция не содержит ни одного элемента, то доступные устройства ввода MIDI отсутствуют. If the returned collection contains no items, then there are no available MIDI input devices. Если в коллекции есть элементы, создайте цикл по объектам DeviceInformation и добавьте имя каждого устройства в список ListBox для устройств ввода MIDI. If there are items in the collection, loop through the DeviceInformation objects and add the name of each device to the MIDI input device ListBox.
Перечисление устройств вывода MIDI работает аналогичным образом, за исключением того, что вам следует указать строку селектора, возвращенную MidiOutPort.GetDeviceSelector при вызове FindAllAsync. Enumerating MIDI output devices works the exact same way as enumerating input devices, except that you should specify the selector string returned by MidiOutPort.GetDeviceSelector when calling FindAllAsync.
Создание вспомогательного класса для наблюдателя устройств Create a device watcher helper class
Пространство имен Windows.Devices.Enumeration предоставляет объект DeviceWatcher, который может уведомлять ваше приложение о добавлении устройства в систему или об удалении его из системы, либо об обновлении информации устройства. The Windows.Devices.Enumeration namespace provides the DeviceWatcher which can notify your app if devices are added or removed from the system, or if the information for a device is updated. Поскольку приложениям с поддержкой MIDI обычно требуются как устройства ввода, так и устройства вывода, в этом примере создается вспомогательный класс, реализующий шаблон DeviceWatcher, а для устройств ввода и вывода MIDI можно использовать один и тот же код, не прибегая к дублированию. Since MIDI-enabled apps typically are interested in both input and output devices, this example creates a helper class that implements the DeviceWatcher pattern, so that the same code can be used for both MIDI input and MIDI output devices, without the need for duplication.
Добавьте в свой проект новый класс, выступающий в качестве наблюдателя устройств. Add a new class to your project to serve as your device watcher. В данном примере он называется MyMidiDeviceWatcher. In this example the class is named MyMidiDeviceWatcher. Остальная часть кода в этом разделе используется для реализации вспомогательного класса. The rest of the code in this section is used to implement the helper class.
Добавьте в класс несколько переменных-членов: Add some member variables to the class:
- Объект DeviceWatcher, который будет отслеживать изменения устройств. A DeviceWatcher object that will monitor for device changes.
- Строку селектора устройства, которая будет содержать строку селектора входного MIDI-порта для одного экземпляра и строку селектора выходного MIDI-порта для другого экземпляра. A device selector string that will contain the MIDI in port selector string for one instance and the MIDI out port selector string for another instance.
- Элемент управления ListBox, который будет заполнен именами доступных устройств. A ListBox control that will be populated with the names of the available devices.
- CoreDispatcher, необходимый для обновления пользовательского интерфейса из потока, отличного от потока пользовательского интерфейса. A CoreDispatcher that is required to update the UI from a thread other than the UI thread.
Добавьте свойство DeviceInformationCollection, которое используется для получения доступа к текущему списку устройств из внешнего вспомогательного класса. Add a DeviceInformationCollection property that is used to access the current list of devices from outside the helper class.
В конструкторе класса вызывающая сторона передает строку селектора MIDI-устройства, объект ListBox со списком устройств и объект Dispatcher, необходимый для обновления пользовательского интерфейса. In class constructor, the caller passes in the MIDI device selector string, the ListBox for listing the devices, and the Dispatcher needed to update the UI.
Вызовите DeviceInformation.CreateWatcher, чтобы создать новый экземпляр класса DeviceWatcher, передав строку селектора MIDI-устройства. Call DeviceInformation.CreateWatcher to create a new instance of the DeviceWatcher class, passing in the MIDI device selector string.
Зарегистрируйте обработчики для обработчиков событий наблюдателя. Register handlers for the watcher’s event handlers.
DeviceWatcher содержит следующие события. The DeviceWatcher has the following events:
- Added. Создается при добавлении в систему нового устройства. Added — Raised when a new device is added to the system.
- Removed. Создается при удалении устройства из системы. Removed — Raised when a device is removed from the system.
- Updated. Создается при обновлении информации, связанной с существующим устройством. Updated — Raised when the information associated with an existing device is updated.
- EnumerationCompleted. Создается, когда наблюдатель завершил перечисление типов запрошенных устройств. EnumerationCompleted — Raised when the watcher has completed its enumeration of the requested device type.
В обработчике событий для каждого из этих событий вызывается вспомогательный метод UpdateDevices, который обновляет ListBox с помощью текущего списка устройств. In the event handler for each of these events, a helper method, UpdateDevices, is called to update the ListBox with the current list of devices. Поскольку UpdateDevices обновляет элементы пользовательского интерфейса, а эти обработчики событий не вызываются в потоке пользовательского интерфейса, каждый вызов должен быть заключен в вызов RunAsync, который запускает указанный код в потоке пользовательского интерфейса. Because UpdateDevices updates UI elements and these event handlers are not called on the UI thread, each call must be wrapped in a call to RunAsync, which causes the specified code to be run on the UI thread.
Вспомогательный метод UpdateDevices вызывает DeviceInformation.FindAllAsync и обновляет ListBox с помощью имен возвращенных устройств, как это было описано ранее в этой статье. The UpdateDevices helper method calls DeviceInformation.FindAllAsync and updates the ListBox with the names of the returned devices as described previously in this article.
Добавьте методы для запуска наблюдателя с помощью метода Start объекта DeviceWatcher и для остановки наблюдателя с помощью метода Stop. Add methods to start the watcher, using the DeviceWatcher object’s Start method, and to stop the watcher, using the Stop method.
Предоставьте деструктор, чтобы отменить регистрацию обработчиков событий для наблюдателя, и установите для наблюдателя устройств значение NULL. Provide a destructor to unregister the watcher event handlers and set the device watcher to null.
Создание портов MIDI для отправки и получения сообщений Create MIDI ports to send and receive messages
В коде программной части для своей страницы объявите переменные-члены для хранения двух экземпляров вспомогательного класса MyMidiDeviceWatcher: один для устройств ввода, а другой для устройств вывода. In the code behind for your page, declare member variables to hold two instances of the MyMidiDeviceWatcher helper class, one for input devices and one for output devices.
Создайте экземпляр вспомогательных классов для наблюдателя, передав строку селектора устройств, чтобы заполнить список ListBox, и объект CoreDispatcher, который может быть получен через свойство Dispatcher этой страницы. Create a new instance of the watcher helper classes, passing in the device selector string, the ListBox to be populated, and the CoreDispatcher object that can be accessed through the page’s Dispatcher property. Затем вызовите этот метод, чтобы запустить DeviceWatcher каждого объекта. Then, call the method to start each object’s DeviceWatcher.
Вскоре после запуска каждого объекта DeviceWatcher он завершит перечисление устройств, которые в настоящий момент подключены к системе, и вызовет его событие EnumerationCompleted, которое обновит список текущих устройств MIDI в каждом объекте ListBox. Shortly after each DeviceWatcher is started, it will finish enumerating the current devices connected to the system and raise its EnumerationCompleted event, which will cause each ListBox to be updated with the current MIDI devices.
Когда пользователь выбирает элемент из списка ListBox входных устройств MIDI, возникает событие SelectionChanged. When the user selects an item in the MIDI input ListBox, the SelectionChanged event is raised. В обработчике для этого события обратитесь к свойству DeviceInformationCollection вспомогательного класса, чтобы получить текущий список устройств. In the handler for this event, access the DeviceInformationCollection property of the helper class to get the current list of devices. Если в списке есть записи, выберите объект DeviceInformation с помощью индекса, соответствующего SelectedIndex элемента управления ListBox. If there are entries in the list, select the DeviceInformation object with the index corresponding to the ListBox control’s SelectedIndex.
Создайте объект MidiInPort, представляющий выбранное устройство ввода, вызвав MidiInPort.FromIdAsync и передав свойство Id выбранного устройства. Create the MidiInPort object representing the selected input device by calling MidiInPort.FromIdAsync, passing in the Id property of the selected device.
Зарегистрируйте обработчик для события MessageReceived, которое вызывается каждый раз при получении MIDI-сообщения через указанное устройство. Register a handler for the MessageReceived event, which is raised whenever a MIDI message is received through the specified device.
Когда вызывается обработчик MessageReceived, это сообщение содержится в свойстве Message для MidiMessageReceivedEventArgs. When the MessageReceived handler is called, the message is contained in the Message property of the MidiMessageReceivedEventArgs. Type объекта сообщения — это значение из перечисления MidiMessageType, указывающее тип полученного сообщения. The Type of the message object is a value from the MidiMessageType enumeration indicating the type of message that was received. Данные сообщения зависят от его типа. The data of the message depends on the type of the message. Этот пример выполняет проверку, определяющую, является ли данное сообщение инициирующим, и если это так, выводит MIDI-канал, примечание и скорость сообщения. This example checks to see if the message is a note on message and, if so, outputs the midi channel, note, and velocity of the message.
Обработчик SelectionChanged для элемента управления ListBox выходного устройства работает аналогично обработчику для входного устройства, только в нем нет зарегистрированных обработчиков событий. The SelectionChanged handler for the output device ListBox works the same as the handler for input devices, except no event handler is registered.
После создания выходного устройства вы можете отправить сообщение, создав IMidiMessage для желаемого типа сообщения. Once the output device is created, you can send a message by creating a new IMidiMessage for the type of message you want to send. В этом примере сообщение — это NoteOnMessage. In this example, the message is a NoteOnMessage. Для отправки этого сообщения вызывается метод SendMessage объекта IMidiOutPort. The SendMessage method of the IMidiOutPort object is called to send the message.
Не забудьте очистить ресурсы приложения после его деактивации. When your app is deactivated, be sure to clean up your apps resources. Отмените регистрацию обработчиков событий и установите значение NULL для объектов входного и выходного MIDI-порта. Unregister your event handlers and set the MIDI in port and out port objects to null. Остановите наблюдатели устройств и установите их в значение NULL. Stop the device watchers and set them to null.
Использование встроенного в Windows синтезатора General MIDI Using the built-in Windows General MIDI synth
При перечислении устройств вывода MIDI, используя описанный выше способ, ваше приложение обнаружит MIDI-устройство «Microsoft GS Wavetable Synth». When you enumerate output MIDI devices using the technique described above, your app will discover a MIDI device called «Microsoft GS Wavetable Synth». Это встроенный синтезатор General MIDI, который можно использовать в приложении. This is a built-in General MIDI synthesizer that you can play from your app. Однако если попытаться создать выходной порт MIDI для этого устройства, возникнет ошибка, если вы не включили расширение SDK для встроенного синтезатора в свой проект. However, attempting to create a MIDI outport to this device will fail unless you have included the SDK extension for the built-in synth in your project.
Включение расширения SDK синтезатора General MIDI в проект приложения To include the General MIDI Synth SDK extension in your app project
- В обозревателе решений щелкните правой кнопкой мыши Ссылки и выберите Добавить ссылку. . In Solution Explorer, under your project, right-click References and select Add reference.
- Разверните узел Универсальное приложение для Windows. Expand the Universal Windows node.
- Выберите Расширения. Select Extensions.
- В списке расширений выберите Microsoft General MIDI DLS для универсальных приложений для Windows. From the list of extensions, select Microsoft General MIDI DLS for Universal Windows Apps.
Если доступно несколько версий расширения, выберите ту из них, которая соответствует целевой версии SDK вашего приложения. If there are multiple versions of the extension, be sure to select the version that matches the target for your app. Вы можете узнать, для какой версии SDK предназначено приложение на вкладке Приложение свойств проекта. You can see which SDK version your app is targeting on the Application tab of the project Properties.