题
我正在写使用C ++和Windows API一个Windows程序,而且,我试图排队在MIDI流MIDI信息,但我收到一个奇怪的错误,当我尝试这样做。如果我使用midiOutShortMsg
发送非排队MIDI消息流中,它工作正常。然而,midiStreamOut
总是返回错误代码68,这是#define
d到MCIERR_WAVE_OUTPUTUNSPECIFIED
。 midiOutGetErrorText
给出了错误的以下描述:
当前MIDI映射设置指的是未安装在系统上一个MIDI设备。使用MIDI映射到编辑设置。
我使用Windows 7(64位),并试图打开与二者MIDI_MAPPER和我的系统上的所有四个MIDI输出设备的设备ID的MIDI流,并且还接收完全相同的错误消息。
下面是打开MIDI流的代码:
UINT device_id = MIDI_MAPPER; //Also tried 0, 1, 2 and 3
midiStreamOpen( &midi, &device_id, 1, ( DWORD_PTR )hwnd, 0, CALLBACK_WINDOW );
下面是发送MIDI消息的代码:
MIDIHDR header;
MIDIEVENT *event;
event = ( MIDIEVENT * )malloc( sizeof( *event ) );
event->dwDeltaTime = delta_time;
event->dwStreamID = 0;
event->dwEvent = ( MEVT_F_SHORT | MEVT_SHORTMSG ) << 24 | ( msg & 0x00FFFFFF );
header.lpData = ( LPSTR )event;
header.dwBufferLength = sizeof( *event );
header.dwBytesRecorded = sizeof( *event );
header.dwUser = 0;
header.dwFlags = 0;
header.dwOffset = 0;
midiOutPrepareHeader( ( HMIDIOUT )midi, &header, sizeof( header ) );
midiStreamOut( midi, &header, sizeof( header ) );
我怎样才能解决这个问题呢?
解决方案
的问题是,我用的是整个事件结构作为缓冲的MIDI流。事实证明,结构,dwParms
的第四构件,实际上应从短消息删去。校正在贴出的问题的代码,两个代码的行可以被改变为如下:
header.dwBufferLength = sizeof( *event ) - sizeof( event->dwParms );
header.dwBytesRecorded = sizeof( *event ) - sizeof( event->dwParms );
当添加多个事件流,它实际上是一个更容易,只需使用DWORD
s的阵列,而不是即使在MIDIEVENT
结构困扰。
有关其他人做使用Windows API编程MIDI,提防一些MSDN文档是误导,不足或完全错误的。
为MIDIEVENT
结构的文档以下表示:
dwParms
如果dwEvent指定MEVT_F_SHORT,不要在流缓存器使用此构件。
这是不明确的,因为它不是清除“使用”是指“包括”而不是“指定”。
下面是在文档中的其他两个缺陷,程序员需要注意的:
dwEvent
事件代码和事件参数或长度。 [...]这一构件的高字节包含标志和事件代码。无论是MEVT_F_LONG或MEVT_F_SHORT标志必须被指定。所述MEVT_F_CALLBACK标志是可选的。
在头文件被选中,MEVT_F_
预处理器定义实际上指定完整DWORD
s而不仅仅是个人的标志,所以在我的代码有问题,指定该成员行应该是如下:
event->dwEvent = MEVT_F_SHORT | MEVT_SHORTMSG << 24 | ( msg & 0x00FFFFFF );
在除此之外,它也证明,含有MIDIHDR结构的存储应保留直到缓冲器已完成播放,所以它应该在堆上分配,而不是在堆栈对于大多数的实现方式。