Allocator

The interfaces to and from the allocator are IMXF and IAllocatorMXF. These interfaces allow you to reuse DMUS_KERNEL_EVENT structures without allocating and deallocating memory. IMXF::PutMessage gives a structure to the allocator and IAllocatorMXF::GetMessage retrieves a freshly zeroed DMUS_KERNEL_EVENT structure from the allocator for reuse. (The allocator gets created with empty DMUS_KERNEL_EVENT structures in the pool so that it never starts out empty.) As shown in the following diagram figure, IRPs (in the form of DMUS_EVENTHEADER structures) come in from dmusic.dll to the unpacker.

Diagram illustrating the flow of IRPs through port and miniport drivers in the allocator process.

The unpacker calls IAllocatorMXF::GetMessage to retrieve an empty DMUS_KERNEL_EVENT structure. The unpacker retrieves the DMUS_KERNEL_EVENT structures from the IRP, fills in these structures (one per MIDI event), and passes them down to the sequencer (using its MXF interface). The sequencer reorders them based on their time stamps and, when they are due, passes them to the miniport driver by calling IMXF::PutMessage. The miniport driver pulls the MIDI data out of the DMUS_KERNEL_EVENT structures so that it can render it into wave data. It passes the used DMUS_KERNEL_EVENT structures back to the allocator with another IMXF::PutMessage call.

The reverse situation happens for capture. MIDI data comes in from the hardware to the miniport driver and the miniport driver calls IAllocatorMXF::GetMessage to get an empty DMUS_KERNEL_EVENT structure. DMUS_KERNEL_EVENT structures are filled with time stamps and data and passed to the capture sink via IMXF::PutMessage. The miniport driver can pass more than one message per structure if it sets the DMUS_KEF_EVENT_INCOMPLETE flag in the DMUS_KERNEL_EVENT structure. The capture sink in the DMus port driver parses this raw data stream and emits DMUS_KERNEL_EVENT structures that contain time-stamped MIDI messages (one per structure).

It is also possible for the miniport driver itself to emit time-stamped messages to the capture sink. In this case, the driver does not set the DMUS_KEF_EVENT_INCOMPLETE bit in DMUS_KERNEL_EVENT. The capture sink passes the time-stamped structures directly to the packer, which packages the messages into IRPs and sends them on to dmusic.dll. DirectMusic capture is only for recording MIDI. For wave recording, use DirectSound capture.

When the packer pulls the data out of a DMUS_KERNEL_EVENT structure, it discards the used DMUS_KERNEL_EVENT structure into the allocator with IMXF::PutMessage. When the IRP buffer is full, it is passed up to dmusic.dll. The packer receives empty IRPs from dmusic.dll, fills them, and completes them. More IRPs keep trickling down so that it always has one to fill.