我正在写使用C ++和Windows API一个Windows程序,而且,我试图排队在MIDI流MIDI信息,但我收到一个奇怪的错误,当我尝试这样做。如果我使用midiOutShortMsg发送非排队MIDI消息流中,它工作正常。然而,midiStreamOut总是返回错误代码68,这是#defined到MCIERR_WAVE_OUTPUTUNSPECIFIEDmidiOutGetErrorText给出了错误的以下描述:

  

当前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 );

当添加多个事件流,它实际上是一个更容易,只需使用DWORDs的阵列,而不是即使在MIDIEVENT结构困扰。

有关其他人做使用Windows API编程MIDI,提防一些MSDN文档是误导,不足或完全错误的。

MIDIEVENT结构的文档以下表示:

  

dwParms

     

如果dwEvent指定MEVT_F_SHORT,不要在流缓存器使用此构件。

这是不明确的,因为它不是清除“使用”是指“包括”而不是“指定”。

下面是在文档中的其他两个缺陷,程序员需要注意的:

  

dwEvent

     

事件代码和事件参数或长度。 [...]这一构件的高字节包含标志和事件代码。无论是MEVT_F_LONG或MEVT_F_SHORT标志必须被指定。所述MEVT_F_CALLBACK标志是可选的。

在头文件被选中,MEVT_F_预处理器定义实际上指定完整DWORDs而不仅仅是个人的标志,所以在我的代码有问题,指定该成员行应该是如下:

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

在除此之外,它也证明,含有MIDIHDR结构的存储应保留直到缓冲器已完成播放,所以它应该在堆上分配,而不是在堆栈对于大多数的实现方式。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top