Requires: winmm.dll - Microsoft Multimedia Win32 library.
Assembly: Bass.Net (in Bass.Net.dll) Version: 188.8.131.52
[SerializableAttribute] public sealed class Midi
<SerializableAttribute> Public NotInheritable Class Midi
The Midi type exposes the following members.
Connects a MIDI input device to a MIDI thru or output device, or connects a MIDI thru device to a MIDI output device.
Disconnects a MIDI input device from a MIDI thru or output device, or disconnects a MIDI thru device from a MIDI output device.
Returns the error message for a given error code.
Sends an input buffer to a specified opened MIDI input device. This function is used for system-exclusive messages.
Closes the specified MIDI input device.
Determines the capabilities of a specified MIDI input device.
Retrieves the number of MIDI input devices in the system.
Sends a message to the MIDI device driver (input).
Opens a MIDI input device.
Prepares a buffer for MIDI input.
Stops input on a given MIDI input device.
Starts MIDI input on the specified MIDI input device.
Stops MIDI input on the specified MIDI input device.
Cleans up the preparation performed by the MIDI_InPrepareHeader(IntPtr, IntPtr) function.
Converts a MIDI note number to its corresponding frequency.
Closes the specified MIDI output device.
Queries a specified MIDI output device to determine its capabilities.
Retrieves the number of MIDI output devices present in the system.
Sends a system-exclusive MIDI message to the specified MIDI output device.
Sends a message to the MIDI device driver (output).
Opens a MIDI output device for playback.
Prepares a MIDI system-exclusive or stream buffer for output.
Turns off all notes on all MIDI channels for the specified MIDI output device.
Sends a short MIDI message to the specified MIDI output device.
Cleans up the preparation performed by the midiOutPrepareHeader function.
Querying MIDI Devices:
Before playing or recording MIDI data, you must determine the capabilities of the MIDI hardware present in the system. MIDI capability can vary from one multimedia computer to the next. Applications should not make assumptions about the hardware present in a given system.
The following functions are provided to determine how many MIDI devices are available for input or output in a given system: MIDI_InGetNumDevs, MIDI_InGetDevCaps(Int32, MIDI_INCAPS), MIDI_OutGetNumDevs and MIDI_OutGetDevCaps(Int32, MIDI_OUTCAPS).
Like other audio devices, MIDI devices are identified by a device identifier, which is determined implicitly from the number of devices present in a given system. Device identifiers range from zero to the number of devices present, minus one. For example, if there are two MIDI output devices in a system, valid device identifiers are 0 and 1. After you determine how many MIDI input or output devices are present in a system, you can inquire about the capabilities of each device. Windows provides the following functions to determine the capabilities of audio devices.
Opening and Closing Device Drivers:
You must open a MIDI device before using it, and you should close the device as soon as you finish using it. The following functions are provided to open and close different types of MIDI devices: MIDI_InOpen(IntPtr, Int32, MIDIINPROC, IntPtr, MIDIFlags), MIDI_InClose(IntPtr), MIDI_OutOpen(IntPtr, Int32, MIDIOUTPROC, IntPtr) and MIDI_OutClose(IntPtr).
Each function that opens a MIDI device takes as parameters a device identifier, an address of a memory location, and some parameters unique to MIDI devices. The memory location is filled with a device handle, which is used to identify the open audio device in calls to other audio functions.
Many MIDI functions can accept either a device handle or a device identifier. Although you can use a device handle wherever you would use a device identifier, you cannot always use a device identifier when a handle is called for.
Note: MIDI devices are not necessarily shareable, so a particular device may not be available when a user requests it. If this happens, the application should notify the user and allow the user to try to open the device again.
Allocating and Preparing MIDI Data Blocks:
The MIDI_OutLongMsg(IntPtr, IntPtr) and MIDI_InAddBuffer(IntPtr, IntPtr) functions require that applications to allocate data blocks to pass to the device drivers for playback or recording purposes. Each of these functions uses a MIDI_HEADER structure to describe its data block.
Before you use one of these functions to pass a data block to a device driver, you must allocate memory for the buffer and the header structure that describes the data block.
The following functions are provided for preparing and cleaning up MIDI data blocks: MIDI_InPrepareHeader(IntPtr, IntPtr), MIDI_InUnprepareHeader(IntPtr, IntPtr), MIDI_OutPrepareHeader(IntPtr, IntPtr) and MIDI_OutUnprepareHeader(IntPtr, IntPtr).
Before you pass a MIDI data block to a device driver, you must prepare the buffer by passing it to the MIDI_InPrepareHeader(IntPtr, IntPtr) or MIDI_OutPrepareHeader(IntPtr, IntPtr) function. When the device driver is finished with the buffer and returns it, you must clean up this preparation by passing the buffer to the MIDI_InUnprepareHeader(IntPtr, IntPtr) or MIDI_OutUnprepareHeader(IntPtr, IntPtr) function before any allocated memory can be freed.
Managing MIDI Data Blocks:
Applications that use data blocks for passing system-exclusive messages (using the MIDI_OutLongMsg(IntPtr, IntPtr) and MIDI_InAddBuffer(IntPtr, IntPtr) functions) and stream buffers must continually supply the device driver with data blocks until playback or recording is complete.
Even if a single data block is used, an application must be able to determine when a device driver is finished with the data block so it can free the memory associated with the data block and header structure. Three methods can be used to determine when a device driver is finished with a data block:
- Specify a callback function to receive a message sent by the driver when it is finished with a data block. To get time-stamped MIDI input data, you must use a callback function.
- Use an event callback (for output only).
- Use a window or thread callback to receive a message sent by the driver when it is finished with a data block. Note: This is not recommended in a .Net environment!
You can write your own callback function to process messages sent by the device driver. To use a callback function, specify the MIDI_CALLBACK_FUNCTION flag in the flags parameter and the address of the callback function in the proc parameter of the MIDI_InOpen(IntPtr, Int32, MIDIINPROC, IntPtr, MIDIFlags) or MIDI_OutOpen(IntPtr, Int32, MIDIOUTPROC, IntPtr) function.
Sending System-Exclusive Messages:
MIDI system-exclusive messages are the only MIDI messages that will not fit into a single Int32 value. System-exclusive messages can be any length. The MIDI_OutLongMsg(IntPtr, IntPtr) function is provided for sending system-exclusive messages to MIDI output devices. To specify MIDI system-exclusive data blocks, use the MIDI_HEADER structure.
After you send a system-exclusive data block using MIDI_OutLongMsg(IntPtr, IntPtr), you must wait until the device driver is finished with the data block before freeing it. If you are sending multiple data blocks, you must monitor the completion of each data block so you know when to send additional blocks.
Note: Any MIDI status byte other than a system-real-time message will terminate a system-exclusive message. If you are using multiple data blocks to send a single system-exclusive message, do not send any MIDI messages other than system-real-time messages between data blocks.
Managing MIDI Recording:
After you open a MIDI device, you can begin recording MIDI data. The following functions are provided for managing MIDI recording: MIDI_InAddBuffer(IntPtr, IntPtr), MIDI_InReset(IntPtr), MIDI_InStart(IntPtr) and MIDI_InStop(IntPtr).
To send buffers to the device driver for recording system-exclusive messages, use MIDI_InAddBuffer(IntPtr, IntPtr). The application is notified as the buffers are filled with system-exclusive recorded data.
The MIDI_InStart(IntPtr) function begins the recording process. When recording system-exclusive messages, send at least one buffer to the driver before starting recording. To stop recording, use MIDI_InStop(IntPtr). Before closing the device by using the MIDI_InClose(IntPtr) function, mark any pending data blocks as being done by calling MIDI_InReset(IntPtr).
Applications that require time-stamped data use a callback function to receive MIDI data.
To record system-exclusive messages with applications that do not use stream buffers, you must supply the device driver with buffers. These buffers are specified by using a MIDI_HEADER structure.
Managing MIDI Thru:
You can connect a MIDI input device directly to a MIDI output device so that when the input device receives an MIM_DATA message, the system sends a message with the same MIDI event data to the output device driver. To connect a MIDI output device to a MIDI input device, use the MIDI_Connect(IntPtr, IntPtr) function.
To achieve the best possible performance with multiple outputs, an application can choose to supply a special form of MIDI output driver, called a thru driver. Although the system allows only one MIDI output device to be connected to a MIDI input device, multiple MIDI output devices can be connected to a thru driver. An application on such a system could connect the MIDI input device to this thru device and connect the MIDI thru device to as many MIDI output devices as needed. For more information about thru drivers, see the Windows device-driver documentation.
Receiving Running-Status Messages:
The Standard MIDI Files 1.0 specification allows the use of running status when a message has the same status byte as the previous message. When running status is used, the status byte of subsequent messages can be omitted. All MIDI input device drivers are required to expand messages using running status into complete messages, so that you always receive complete MIDI messages from a MIDI input device driver.
Handling Errors with MIDI Functions:
MIDI audio functions return a nonzero error code. For MIDI-associated errors, the MIDI_GetErrorText(Boolean, Int32) functions retrieve textual descriptions for the error codes. The application must still look at the error value itself to determine how to proceed, but it can use the error descriptions in dialog boxes to inform users of the error conditions.
The only MIDI functions that do not return error codes are the MIDI_InGetNumDevs and MIDI_OutGetNumDevs functions. These functions return a value of zero if no devices are present in a system or if any errors are encountered by the function.
This class does not implement MIDI Streams (see the Un4seen.Bass.AddOn.Midi add-on for real-time playback of MIDI streams)!