Компоненты MIDI и DirectMusic
Для захвата и воспроизведения потоков MIDI и DirectMusic в приложениях используется сочетание компонентов режима пользователя и режима ядра.
Приложение может использовать один из следующих программных интерфейсов для воспроизведения и записи MIDI:
Функции midiOutXxx и midiInXxx в Microsoft Windows Multimedia
DirectMusic API
Поведение функций midiOutXxx и midiInXxx основано на возможностях устаревших драйверов и устройств MIDI. Начиная с Windows 98 , системный драйвер WDMAud преобразует вызовы этих функций в команды для аудиодрайверов WDM. Однако, эмулируя поведение старых программ и оборудования, функции midiOutXxx и midiInXxx жертвуют точностью времени и расширенными функциями, которые теперь доступны через API DirectMusic. Дополнительные сведения о directMusic и функциях MIDI Windows Multimedia см. в документации по Microsoft Windows SDK.
Функции DIRECTMusic и Windows Multimedia MIDI являются клиентами системного драйвера SysAudio, который создает графы фильтра звука, обрабатывающие потоки MIDI и DirectMusic. Построение графа прозрачно для приложений, использующих эти программные интерфейсы.
Компоненты MIDI
На следующем рисунке показаны компоненты пользовательского режима и режима ядра, которые приложение MIDI использует для воспроизведения данных MIDI. Это приложение взаимодействует с аудиодрайверами WDM через функции midiOutXxx , реализованные в системном компоненте WinMM, Winmm.dll.
Приложение MIDI на предыдущем рисунке считывает события MIDI с метками времени из файла MIDI и воспроизводит их. Драйверы miniport MIDI и DMus отображаются в виде затемненных прямоугольников, чтобы указать, что они могут быть компонентами, предоставляемыми поставщиком. При необходимости поставщик может использовать один из предоставляемых системой драйверов минипорта — FMSynth, UART или DMusUART — вместо написания пользовательского драйвера минипорта. Все остальные компоненты на рисунке предоставляются системой.
Цикл main типичного приложения воспроизведения MIDI вызывает timeSetEvent для планирования следующего события заметок или заметок. Этот вызов принимает в качестве одного из параметров указатель функции на подпрограмму обратного вызова приложения. Когда происходит событие и операционная система вызывает подпрограмму обратного вызова, эта подпрограмма вызывает midiOutShortMsg , чтобы включить или отключить одну или несколько запланированных заметок. Функция midiOutShortMsg сохраняет сообщения MIDI в буферах данных, заблокированных на странице, чтобы исключить необходимость в использовании этой памяти во время вызова. Дополнительные сведения о вызовах timeSetEvent и midiOutShortMsg см. в документации по Microsoft Windows SDK.
WDMAud, состоящий из компонентов режима пользователя и ядра (Wdmaud.drv и Wdmaud.sys), записывает время поступления необработанных сообщений MIDI из вызовов midiOutShortMsg . WDMAud объединяет эти метки времени с сообщениями MIDI для создания потока MIDI, который он отправляет в один из компонентов режима ядра, которые отображаются под WDMAud на рисунке.
При создании графа фильтра звука для приложения MIDI SysAudio выбирает только одно из трех возможных подключений — к SWMidi, MIDI-порту или драйверу порта DMus, которые отображаются на предыдущем рисунке. Если приложение выбирает устройство MIDI по умолчанию, SysAudio сначала ищет синтезатор, у которого драйвер MIDI или DMus miniport имеет pin-код MIDI. Если такое устройство не обнаруживается в реестре, SysAudio будет использовать системный драйвер SWMidi (Swmidi.sys). SWMidi — это фильтр KS, реализующий волновой синтезатор в программном обеспечении. Для этого требуется только устройство, которое может визуализировать волновой звуковой поток.
SWMidi смешивает все свои голоса, чтобы создать одноволновой поток PCM, который он выводит в системный драйвер KMixer. KMixer, в свою очередь, передает волновый поток в формате PCM устройству WaveCyclic или WavePci, порты и мини-порты которого отображаются в левом нижнем углу рисунка. Кроме того, KMixer может передавать свой выходной поток на звуковое usb-устройство, управляемое системным драйвером класса USBAudio (не показано на рисунке).
На предыдущем рисунке драйвер порта MIDI принимает поток MIDI с меткой времени из WDMAud и преобразует его в необработанные сообщения MIDI, которые драйвер минипорта MIDI воспроизводит через устройство синтезатора. Драйвер порта MIDI содержит секвенсор, который реализован в программном обеспечении и может планировать необработанные сообщения MIDI с разрешением таймера в одну миллисекунды.
Драйвер порта DMus может достичь гораздо более высокой точности времени, чем драйвер порта MIDI, если устройство синтезатора содержит аппаратный секвенсор. В этом случае драйвер DMus miniport должен указать аппаратный буфер, который достаточно велик, чтобы поглощать дрожание, возникающее в результате конкуренции за время ЦП с ISR (подпрограммами прерывания обслуживания) и другими высокоприоритетными операциями. Метки времени в потоке MIDI, который драйвер порта DMus выводит в драйвер мини-порта, представляют собой 64-разрядные значения с разрешением 100 наносекунд.
Если синтезатор DMusic не имеет аппаратного секвенсора, он должен полагаться на программный секвенсор драйвера портов DMus, который, как и драйвер порта MIDI, имеет разрешение таймера в одну миллисекунды.
Драйвер адаптера создает драйвер порта MIDI или DMus, вызывая PcNewPort со значением GUID CLSID_PortMidi или CLSID_PortDMus соответственно. В Windows XP и более поздних версиях драйверы портов MIDI и DMus используют одну и ту же реализацию программного обеспечения.
В нижней части предыдущего рисунка отображаются названия системных драйверов miniport FMSynth, UART и DMusUART, которые включены в Portcls.sys. Драйвер адаптера создает один из этих драйверов мини-порта, вызывая PcNewMiniport. FMSynth и UART предоставляют интерфейсы IMiniportMidi , а DMusUART — интерфейс IMiniportDMus . Обратите внимание, что UART теперь устарел (после Windows 98 Gold) и поддерживается только для существующих драйверов. Новые драйверы адаптера должны вместо этого использовать DMusUART (в Windows 98 SE и более поздних версиях, а также в Windows 2000 и более поздних версиях), который реализует надмножество функций UART. DMusUART — это пример драйвера мини-порта DMus, который не поддерживает ни загрузки DLS, ни виртуализацию оборудования. Исходный код драйверов минипорта FMSynth и DMusUART доступен в примерах аудиодрайверов в комплекте драйверов Windows (WDK).
На следующем рисунке показаны компоненты пользовательского режима и режима ядра, которые программа MIDI использует для сбора данных MIDI. Это приложение взаимодействует с аудиодрайверами WDM через функции midiInXxx .
На предыдущем рисунке драйверы miniport MIDI и DMus отображаются в виде затемненных прямоугольников, указывающих, что они могут быть компонентами, предоставляемыми поставщиком. При необходимости поставщик может вместо этого использовать один из системных драйверов miniport, UART или DMusUARTCapture. Все остальные компоненты на рисунке предоставляются системой.
Источником данных MIDI обычно является устройство MPU-401. Вызывая PcNewMiniport, драйвер адаптера может создать один из системных драйверов минипорта, UART или DMusUARTCapture, для записи данных MIDI с устройства MPU-401. Опять же, UART устарел, и новые драйверы должны использовать DMusUARTCapture (в Windows 98 SE и более поздних версиях, а также в Windows 2000 и более поздних версиях).
Каждый раз при возникновении события включения или заметок MIDI драйвер мини-порта записи MIDI или DMusic (в нижней части предыдущего рисунка) добавляет метку времени к сообщению MIDI перед добавлением его в поток MIDI, который передается в драйвер порта MIDI или DMus.
Драйвер порта записи MIDI или DMusic выводит поток MIDI с меткой времени в Wdmaud.sys, половину системного драйвера WDMAud в режиме ядра. Половина пользовательского режима, Wdmaud.drv, выводит поток MIDI с метками времени в программу приложения с помощью функций midiInXxx , которые реализуются в Winmm.dll.
Приложение MIDI в верхней части рисунка записывает события MIDI с метками времени в файл MIDI. В то время, когда приложение вызывает midiInOpen для открытия входного потока MIDI, оно передает указатель функции на свою подпрограмму обратного вызова. При возникновении события заметок или заметок операционная система вызывает подпрограмму обратного вызова с блоком данных, который включает одно или несколько сообщений MIDI с меткой времени. Метки времени в этих сообщениях по сути совпадают с изначально созданными драйвером MIDI или DMus miniport.
Компоненты DirectMusic
На следующем рисунке показаны компоненты пользовательского режима и режима ядра, которые используются приложением DirectMusic для воспроизведения или записи данных MIDI.
Компоненты воспроизведения отображаются в левой половине предыдущего рисунка, а компоненты захвата — справа. Драйверы мини-порта DMus отображаются в виде затемненных полей, указывающих на то, что они могут быть компонентами, предоставляемыми поставщиком. При необходимости поставщик может использовать один из предоставляемых системой драйверов miniport, DMusUART или DMusUARTCapture. Другие компоненты на рисунке предоставляются системой.
В левом верхнем углу рисунка приложение DirectMusic направляет поток MIDI с меткой времени из файла в системный компонент DirectMusic в пользовательском режиме (DMusic.dll), который, в свою очередь, направляет поток в драйвер порта DMus. Этот драйвер можно привязать к драйверу мини-порта для устройства Synth DirectMusic или MPU-401, если он доступен. Кроме того, драйвер порта можно привязать к системным драйверу DMusic (Dmusic.sys), который является системным драйвером DMus miniport, который реализует волновой синтезатор с поддержкой DLS в программном обеспечении и для которого требуется только устройство, которое может визуализировать волновой звуковой поток.
Как и SWMidi, драйвер DMusic, Dmusic.sys, смешивает все свои голоса вместе, чтобы создать один поток волн в формате PCM, который он выводит в KMixer. KMixer, в свою очередь, может передавать поток волны на волновое устройство, порты которого и драйверы минипорта отображаются в левом нижнем углу рисунка, или на звуковое USB-устройство, управляемое системным драйвером USBAudio, который не отображается на рисунке.
Компоненты записи DirectMusic отображаются в правой половине предыдущего рисунка. Драйвер мини-порта для захвата DMusic в правом нижнем углу рисунка управляет оборудованием захвата и метками времени для каждого записанного сообщения MIDI. Драйвер порта DMus направляет поток MIDI с меткой времени к компоненту DirectMusic в пользовательском режиме, DMusic.dll. Приложение обращается к этому потоку через API DirectMusic и записывает данные MIDI с метками времени в файл.
Драйвер адаптера может использовать системный драйвер мини-порта DMusUARTCapture для управления устройством захвата MPU-401. Драйвер адаптера создает этот драйвер мини-порта, вызывая PcNewMiniport со значением GUID CLSID_DMusUARTCapture. Полученный объект драйвера miniport поддерживает интерфейс IMiniportDMus . Исходный код драйвера для мини-порта DMusUARTCapture доступен в примерах аудиодрайверов в комплекте драйверов Windows (WDK).
Приложение DirectMusic также может выполняться через устройство midiOutXxx , например SWMidi (Swmidi.sys), если это необходимо. Для простоты этот путь опущен на предыдущем рисунке. Для правильной работы драйвера DMusic (Dmusic.sys) требуется начальная загрузка DLS; использование SWMidi позволяет избежать этого требования.