使用midi*函数进行音乐播放

本文介绍了如何使用midiOutOpen等函数进行MIDI音乐输出,包括打开默认MIDI设备、选择MIDI设备、输出MIDI数据以及回调函数的使用。通过示例代码展示了输出C、E、G三个音符的过程。
摘要由CSDN通过智能技术生成

早在刚学习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

在沉寂了一段时间之后。我开始开发游戏的音频程序了。今天我要为大家展示的是我写的播放MIDI的程序,其实不要以为MIDI的载入和播放很复杂,其实它是相当的简单、只需要选用合适的解码器就行了。现在又几种解码器可以选择。MCI和DirectMusic。其中MCI是windows特别对多媒体应用程序提供的API集合,它可以播放很多流行的格式。但是对MIDI的控制性比较低。而DirectMusic则对MIDI有着较丰富的支持,最典型的就是可以控制节奏(tempo)。 我的代码没有对DirectMusic进行封装,使用C的风格制作的。所以大家看起来很好理解。下面我就来展示我写的代码吧。 Main.cpp /*--------------------------------------------------------------------------- 蒋轶民制作E-mail:jiangcaiyang123@163.com 最后编辑:年月日:29:06 文件名:main.cpp 作用:头文件的实现 ----------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ // 头文件 #include #include #include "main.h" using namespace std; int main( int, char** ) { try { cout << "初始化设备\n"; Initialize();// 初始化DirectMusic cout << "载入声音\n"; LoadSound( TEXT( "test.mid" ) ); // 载入声音文件 cout <SetRepeats( NULL ); // 仅仅播放一次 SetVolume( 0, 0 ); Play(); Sleep( 1000 ); SetTempo( 160 ); cout << "当前播放的速率为" << GetCurrentTempo() << '\n'; while ( IsPlaying() ); UnInitialize(); cout << "释放设备\n"; } catch( CError& e ) { e.SaveToFile(); cout << "错误报告已保存。\n"; } catch( ... ) { cout << "遇到了未知的错误。\n"; } return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值