在Windows中使用MIDI流时出现问题 我用C++和Windows API编写Windows程序,我试图在MIDI流中排队MIDI消息,但是当我尝试这样做时,我收到了一个奇怪的错误。如果我使用midiOutShortMsg向流发送未排队的MIDI消息,它将正常工作。但是,midristreamout总是返回错误代码68,即\defined到MCIERR\u WAVE\u OUTPUTUNSPECIFIEDmidiOutGetErrorText给出了以下错误描述:

在Windows中使用MIDI流时出现问题 我用C++和Windows API编写Windows程序,我试图在MIDI流中排队MIDI消息,但是当我尝试这样做时,我收到了一个奇怪的错误。如果我使用midiOutShortMsg向流发送未排队的MIDI消息,它将正常工作。但是,midristreamout总是返回错误代码68,即\defined到MCIERR\u WAVE\u OUTPUTUNSPECIFIEDmidiOutGetErrorText给出了以下错误描述:,c++,windows,winapi,midi,C++,Windows,Winapi,Midi,当前的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_PT

当前的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 ) );
MIDIHDR报头;
MIDIEVENT*事件;
事件=(MIDIEVENT*)malloc(sizeof(*事件));
事件->dwDeltaTime=增量时间;
事件->dwStreamID=0;

event->dwEvent=(MEVT_F_SHORT | MEVT_SHORTMSG)问题是我使用整个事件结构作为MIDI流的缓冲区。事实证明,该结构的第四个成员,
dwParms
,实际上应该从短消息中省略。要更正已发布问题中的代码,可以将其中两行代码更改为以下内容:

header.dwBufferLength = sizeof( *event ) - sizeof( event->dwParms );
header.dwBytesRecorded = sizeof( *event ) - sizeof( event->dwParms );
在向流中添加多个事件时,实际上只使用
DWORD
s数组比使用
MIDIEVENT
结构要容易得多

对于使用Windows API进行MIDI编程的其他人,请注意某些MSDN文档具有误导性、不充分或完全错误

MIDIEVENT
结构的文档说明如下:

header.dwBufferLength = sizeof( *event ) - sizeof( event->dwParms );
header.dwBytesRecorded = sizeof( *event ) - sizeof( event->dwParms );
德帕姆斯

如果dwEvent指定MEVT_F_SHORT,则不要在流缓冲区中使用此成员

这是不明确的,因为不清楚“使用”的意思是“包括”而不是“指定”

以下是程序员需要注意的文档中的另外两个缺陷:

dwEvent

事件代码和事件参数或长度。[…]此成员的高位字节包含标志和事件代码。必须指定MEVT_F_LONG或MEVT_F_SHORT标志。MEVT_F_回调标志是可选的

当检查头文件时,
MEVT\u F\u
预处理器定义实际上指定了complete
DWORD
s,而不仅仅是单个标志,因此在我的问题代码中,指定此成员的行应该如下所示:

event->dwEvent = MEVT_F_SHORT | MEVT_SHORTMSG << 24 | ( msg & 0x00FFFFFF );
event->dwEvent=MEVT_F_SHORT | MEVT_SHORTMSG