質問

私はC ++とWindows APIを使用してWindowsプログラムを書いています。MIDIストリームでMIDIメッセージをキューに入れようとしていますが、そうしようとすると奇妙なエラーを受け取っています。使用する場合 midiOutShortMsg クロックでないMIDIメッセージをストリームに送信するために、正しく機能します。でも、 midiStreamOut 常にエラーコード68を返します #defined to MCIERR_WAVE_OUTPUTUNSPECIFIED. midiOutGetErrorText エラーの次の説明を示します。

現在のMIDIマッパーセットアップは、システムにインストールされていないMIDIデバイスを指します。 MIDIマッパーを使用してセットアップを編集します。

Windows 7(64ビット)を使用しており、MIDI_MAPPERと4つの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ストリームのバッファーとしてイベント構造全体を使用していたことです。構造の4番目のメンバー、 dwParms, 、実際には短いメッセージから省略する必要があります。投稿された質問のコードを修正するために、コードの2つの行を次のように変更できます。

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を指定している場合、このメンバーをStream Bufferで使用しないでください。

これは、「使用」が「指定」ではなく「」を意味することを意図していることは明らかではないため、あいまいです。

ドキュメントには、プログラマーが認識する必要がある他の2つの欠陥があります。

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