早在刚学习MFC的时候就差了很多关于音乐播放的事,知道了一些winmm.dll中的函数,不过当时印象最深的是mci*函数,可以用来播放各种媒体音乐,还能控制光驱的开关。毕竟刚学习程序的人都是最先关心两件事,一个就是多媒体控制,另一个就是硬件的端口控制,mciSendString就恰好兼具两个特性。后来找了好多资料来了解midi,但因为不知道应该用什么来操作midi设备,所以没有着手学习midi,始终上网查找或是看关于midi的书都是关注如何使用函数来操作midi,然而那些书都没用使用简简单单的API或是指代不是很清楚。知道昨天看到了一篇文章,应该是这篇吧,记不太清除了。 http://www.giordanobenicchi.it/midi-tech/lowmidi.htm :
Using the Low level MIDI API, you need to first call midiOutOpen() or midiInOpen() to open some MIDI device for output or input respectively.
In order to write out MIDI data to a particular device, you need to first call midiOutOpen() once, passing it the Device ID of that desired device. Then, you can subsequently call a function such as midiOutShortMsg() which (immediately) outputs MIDI data to that device.
In order to read incoming MIDI data from a particular device, you need to first call midiInOpen() once, passing it the Device ID of that desired device. Then, Windows will subsequently pass your program each incoming MIDI message from that device.
After you're done inputting or outputting to a device (and have no further use for it), you must close that device.
Think of a MIDI device like a file. You open it, you read or write to it, and then you close it.
Opening the default MIDI device for input or output
How does your program choose a MIDI device for input or output? There are several different approaches you can take, depending upon how fancy and flexible you want your program to be.
Recall that Windows maintains separate lists of the devices which are capable of inputting MIDI data, and the devices capable of outputting MIDI data. Remember that the first device in each list has a Device ID of 0. This would be the "default" MIDI Input device and MIDI Output device respectively. So, if you simply want to open the default MIDI Output device, then use a Device ID of 0 with midiOutOpen() as so:
unsigned long
result;
HMIDIOUT outHandle;
/* Open the default MIDI Out device */
result = midiOutOpen(&outHandle, 0, 0, 0, CALLBACK_NULL);
if
(result)
{
printf("There was an error opening the default MIDI Out device!/r/n");
}
Of course, if the user has no device installed capable of outputting or playing MIDI data, the above call returns an error, so always check that return value.
Likewise, use a Device ID of 0 with midiInOpen() to open the default MIDI Input device. (Note that these two default devices may or may not be components of the same card. In other words, whichever MIDI IN jack is the default MIDI Input, and whichever MIDI OUT jack is the default MIDI Output, could be on two entirely different cards. But that is irrelevant to your purposes).
unsigned long
result;
HMIDIIN inHandle;
/* Open the default MIDI In device. Note: myWindow is a handle to some open window */
result = midiInOpen(&inHandle, 0, (DWORD)myWindow, 0, CALLBACK_WINDOW);
if
(result)
{
printf("There was an error opening the default MIDI In device!/r/n");
}
So what actually is the default MIDI Output device? Well, that's whatever device that the user choose from the list of MIDI Output devices under "Single Instrument" of Control Panel's Multimedia utility (ie, on the "MIDI" page). The list on this page is Windows actually displaying all of the names that were added to its list of devices capable of outputting or playing MIDI data.
On the other hand, the default MIDI Input device is whichever MIDI device happened to first get into the list of MIDI Input devices upon bootup. The user really has no control over setting this.
Opening the MIDI Mapper for output
Whereas the above method would work to choose the MIDI Output device, there is another option you can use instead. You can open the MIDI Mapper for MIDI output. What is the advantage of this? Well, it allows the user to use the MIDI Mapper to route the MIDI data (according to MIDI channel) to different output devices. For example, he could set all MIDI events on channel 1 to go to the built-in wavetable module on his Creative Labs sound card, and all MIDI events on channel 2 to go to the built-in wavetable on his Turtle Beach sound card. In this way, although your program outputs to only one device, it actually supports having the various MIDI channels going to different devices (which the user may desire for more polyphony or because some cards are better suited for certain sounds, etc).
NOTE: In Windows 95, the MIDI Mapper settings are actually the "Custom configuration" settings upon the Multimedia utility's MIDI page. These allow for even more flexible routing of MIDI data, plus the "Add new Instrument" feature allows the user to apply Instrument Definition Files thus remapping your program's MIDI output even more, for example, to make non-General MIDI instruments conform to General MIDI.
The MIDI Mapper has a defined Device ID of -1, so to open MIDI Mapper for MIDI Output:
unsigned long
result;
HMIDIOUT outHandle;
/* Open the MIDI Mapper. Note: myWindow is a handle to some open window */
result = midiOutOpen(&outHandle, (UINT)-1, (DWORD)myWindow, 0, CALLBACK_WINDOW);
if
(result)
{
printf("There was an error opening MIDI Mapper!/r/n");
}
One drawback with MIDI Mapper is that it does impose an extra layer of software processing upon your MIDI output. If the user never enables the "Custom configuration", then all MIDI data ends up going to one device anyway, so you gain nothing here (and lose a little efficiency).
The most flexible way to choose a MIDI device for input or output
The most flexible way would be to present the user with all of the names in the list of MIDI Output devices and let him choose which one he wants (or if your program supports multiple MIDI output devices, you may wish to let him pick out several names from the list, and assign each sequencer "track" to one of those Device IDs. This is how professional sequencers implement support for multiple cards/outputs).
Whereas Windows maintains separate lists of MIDI Input and Output devices, so too, Windows has separate functions for querying the devices in each list.
Windows has a function that you can call to determi