Функции работы с аудио-устройством
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

В модуле midi _ pin реализованы все функции, которые обеспечивают работу с музыкальным пином на уровне ядра. В работе с музыкальным пином используются запросы на установку состояния пина и отправление пакетов с музыкальными данными.

NTSTATUS PinInit()

В этой функции происходит инициализация полей заголовка IRP-пакета и MIDI-данных, которые используются во время отправления музыкальных команд в пин. Далее в функциях PinMidiNoteOn и PinMidiNoteOff используется инициализированный заголовок.

Инициализация заголовка IRP-пакета происходит следующим образом:

typedef __declspec(align(16)) struct _MIDI_DATA

{KSMUSICFORMAT InstrumentFormat;    // include <ksmedia.h>

union

{UCHAR InstrumentByte[4];

UCHAR NoteOffByte[4];};

KSMUSICFORMAT NoteFormat;

UCHAR NoteOnByte[4];

} MIDI_DATA, * PMIDI_DATA;

MIDI_DATA PinMidiData;

KSSTREAM_HEADER PinWriteHeader; // include <ks.h>

RtlZeroMemory(&PinWriteHeader, sizeof(PinWriteHeader));

// 12 байт

PinMidiData.InstrumentFormat.TimeDeltaMs = 0;

PinMidiData.InstrumentFormat.ByteCount = 3;

PinMidiData.InstrumentByte[0] = 0x00;

PinMidiData.InstrumentByte[1] = 0x00;

PinMidiData.InstrumentByte[2] = 0x00;

PinMidiData.InstrumentByte[3] = 0x00;

// ещё 12 байт

PinMidiData.NoteFormat.TimeDeltaMs = 0;

PinMidiData.NoteFormat.ByteCount = 3;

PinMidiData.NoteOnByte[0] = 0x00;

PinMidiData.NoteOnByte[1] = 0x00;

PinMidiData.NoteOnByte[2] = 0x00;

PinMidiData.NoteOnByte[3] = 0x00;

PinWriteHeader.Size = sizeof(PinWriteHeader);

PinWriteHeader.TypeSpecificFlags = 0;

PinWriteHeader.PresentationTime.Time = 0;

PinWriteHeader.PresentationTime.Numerator = 1;

PinWriteHeader.PresentationTime.Denominator = 1;

PinWriteHeader.Duration = 0;

PinWriteHeader.FrameExtent = 24; // всего 24 байта

PinWriteHeader.DataUsed = 24; // всего 24 байта

PinWriteHeader.Data = &PinMidiData;

NTSTATUS PinOpenStream(IN HANDLE UserPin)

Когда через запрос IOCTL_SHARE_PIN драйвер получает объект открытого пина, то необходимо вызвать эту функцию. В ней происходит вызов функции ObReferenceObjectByHandle для того, чтобы получить указатель на объект пина в режиме ядра и увеличить число ссылок на объект. Это делается для того, чтобы объект пина не был удалён из таблицы объектов ОС после заверешения работы пользовательского приложения, в котором был создан объект пина. Также здесь происходит установка флага, что пин открыт для драйвера.

UserPin – HANDLE того пина, который содержится в буфере IRP-пакета.

NTSTATUS PinIsOpenedStream()

Возвращает STATUS_SUCCESS если пин открыт.

NTSTATUS PinFree()

Здесь происходит вызов функции ObDereferenceObject, которая уменьшает число ссылок на объект пина.

NTSTATUS PinSetState(IN KSSTATE State)

Устанавливает состояние пина в State (KSSTATE_RUN, KSSTATE_PAUSE или KSSTATE_STOP). Перед тем, как воспроизводить ноты, необходимо установить состояние пина в KSSTATE_RUN. Функция работает только при IRQL = PASSIVE_LEVEL.

NTSTATUS PinWriteData(IN KSSTREAM_HEADER * Pheader)

Отправляет заголовок в открытый пин посредством IOCTL_KS_WRITE_STREAM.

Функция работает только при IRQL = PASSIVE_LEVEL.

NTSTATUS PinMidiNoteOn(IN UCHAR Channel,

IN UCHAR Instrument, IN UCHAR Note)

Если пин открыт, то отправляет команду на воспроизведение ноты Note с использованием инструмента Instrument в канале Channel.

Модификация инициализированного заголовка:

PinMidiData.InstrumentByte[0] = 0xC0 | Channel;

PinMidiData.InstrumentByte[1] = Instrument;

PinMidiData.NoteOnByte[0] = 0x90 | Channel;

PinMidiData.NoteOnByte[1] = Note;

PinMidiData.NoteOnByte[2] = 0x7F;

// 24 байта отправляем, т.к. в одном

PinWriteHeader.FrameExtent = 24; // пакете 2 команды: устанавливаем

PinWriteHeader.DataUsed = 24; // инструмент и отправляем ноту

PinWriteData(&PinWriteHeader);

Функция работает только при IRQL = PASSIVE_LEVEL.

NTSTATUS PinMidiNoteOff(IN UCHAR Channel, IN UCHAR Note)

Выключает ноту Note в канале Channel.

Модификация инициализированного заголовка:

PinMidiData.NoteOffByte[0] = 0x80 | Channel;

PinMidiData.NoteOffByte[1] = Note;

PinWriteHeader.FrameExtent = 12; // 12 байт шлём, т.к. в одном пакете

PinWriteHeader.DataUsed = 12; // 1 команда: выключаем ноту

PinWriteData(&PinWriteHeader);

Функция работает только при IRQL = PASSIVE_LEVEL.

 

Дата: 2019-12-22, просмотров: 222.