Once you open a waveform input device, you can begin recording MIDI data. The Multimedia extensions provide the following functions for managing MIDI recording:
midiInAddBuffer
Sends a buffer to the device driver so it can be filled with recorded MIDI data.
midiInReset
Stops MIDI recording and marks all pending buffers as done.
midiInStart
Starts MIDI recording and resets the time stamp to zero.
midiInStop
Stops MIDI recording.
Use the midiInAddBuffer function to send data buffers to the device driver for recording system-exclusive messages. As the buffers are filled with recorded data, the application is notified by one of the techniques discussed in “Managing Audio Data Blocks,” earlier in this chapter.
Use the midiInStart function to begin recording. To record system-exclusive messages, send at least one buffer to the driver before starting recording. To stop recording, use midiInStop. Before closing the device using midiInClose, call midiInReset to mark any pending data blocks as being done.
You must use either a window-procedure function or a low-level callback function to receive MIDI data. If you want time-stamped data, you must use a low-level callback function.
To record system-exclusive messages, you must supply the device driver with data buffers. These buffers are specified by a MIDIHDR data structure. This is the same data structure used for MIDI system-exclusive playback described in “Sending System-Exclusive Messages,” earlier in this chapter. Memory for the MIDIHDR structure and its accompanying data buffer must be allocated and prepared as shown in “Allocating and Preparing Audio Data Blocks,” earlier in this chapter.
The following messages can be sent to a window-procedure function for managing MIDI recording:
Message | Description |
MM_MIM_CLOSE | Sent when the device is closed using midiInClose. |
MM_MIM_DATA | Sent when a complete MIDI message is received (this message is used for all MIDI messages except system-exclusive messages). |
MM_MIM_ERROR | Sent when an invalid MIDI message is received (this message is used for all MIDI messages except system-exclusive messages). |
MM_MIM_LONGDATA | Sent when either a complete MIDI system-exclusive message is received, or when a data buffer sent using midiInAddBuffer is filled with system-exclusive data. |
MM_MIM_LONGERROR | Sent when an invalid MIDI system-exclusive message is received. |
MM_MIM_OPEN | Sent when the device is opened using midiInOpen. |
A wParam and lParam parameter is associated with each of these messages. The wParam parameter always specifies a handle to the open MIDI device. The lParam parameter is unused for the MM_MIM_CLOSE and MM_MIM_OPEN messages.
Summary: Receiving Regular MIDI Data
For the MM_MIM_DATA message, lParam specifies the received MIDI data. This data is packed into a DWORD, as shown in the following illustration:
Summary: Receiving System-Exclusive MIDI Data
For the MM_MIM_LONGDATA message, lParam specifies a far pointer to a MIDIHDR structure that identifies the data buffer for system-exclusive messages. The data buffer might not be completely filled—you usually don't know the size of the system-exclusive messages before recording them and must allocate a buffer large enough for the largest expected message. Use the dwBytesRecorded field of the MIDIHDR structure to determine the amount of valid data present in the buffer.
This syntax of the low-level callback function for MIDI input devices is as follows:
void FAR PASCAL midiInCallback(hMidiIn, wMsg, dwInstance, dwParam1, dwParam2)
The following messages can be sent to the wMsg parameter of MIDI input callback functions:
Message | Description |
MIM_CLOSE | Sent when the device is closed using midiInClose. |
MIM_DATA | Sent when a complete MIDI message is received (this message is used for all MIDI messages except system-exclusive messages). |
MIM_ERROR | Sent when an invalid MIDI message is received (this message is used for all MIDI messages except system-exclusive messages). |
MIM_LONGERROR | Sent when an invalid MIDI system-exclusive message is received. |
MIM_LONGDATA | Sent when either a complete MIDI system- exclusive message is received, or when a data buffer is filled with system-exclusive data. |
MIM_OPEN | Sent when the device is opened using midiInOpen. |
These messages are similar to those sent to window-procedure functions, but the parameters are different. A handle to the open MIDI device is passed as a parameter to the callback, along with the DWORD of instance data that was passed using midiInOpen.
The callback has two message-dependent parameters: dwParam1 and dwParam2. For the MIM_OPEN and MIM_CLOSE messages, these parameters are unused.
For the MIM_DATA message, dwParam1 specifies the received MIDI data and dwParam2 specifies a time stamp for the data. The data is packed into a DWORD, as shown in the previous section on using window messages.
For the MIM_LONGDATA message, dwParam1 specifies a far pointer to a MIDIHDR structure that identifies the data buffer for system-exclusive messages. As with the MIM_DATA message, dwParam2 specifies a time stamp for the data. The data buffer might not be completely filled. Use the dwBytesRecorded field of the MIDIHDR structure to determine the amount of valid data present in the buffer.
After the device driver is finished with a data block, you can clean up and free the data block. Because of the restrictions of low-level audio callbacks, you can't do this within the callback. You must set some semaphores and do this outside of the callback.