Frage

Ich schreibe ein Windows -Programm mit C ++ und der Windows -API. Ich versuche, MIDI -Nachrichten in einem MIDI -Stream zu verbinden, erhalte aber einen seltsamen Fehler, wenn ich dies versuche. Wenn ich benutze midiOutShortMsg Um eine MIDI-Nachricht nicht an den Stream zu senden, funktioniert sie korrekt. Jedoch, midiStreamOut Gibt immer den Fehlercode 68 zurück, was ist #defineD an MCIERR_WAVE_OUTPUTUNSPECIFIED. midiOutGetErrorText Gibt die folgende Beschreibung des Fehlers an:

Das aktuelle MIDI Mapper -Setup bezieht sich auf ein MIDI -Gerät, das nicht auf dem System installiert ist. Verwenden Sie Midi Mapper, um das Setup zu bearbeiten.

Ich verwende Windows 7 (64-Bit) und habe versucht, den MIDI-Stream mit Geräte-IDs sowohl von MIDI_Mapper als auch allen vier MIDI-Ausgabegeräten auf meinem System zu öffnen, und empfange immer noch die gleiche Fehlermeldung.

Hier ist der Code zum Öffnen des MIDI -Streams:

UINT device_id = MIDI_MAPPER; //Also tried 0, 1, 2 and 3
midiStreamOpen( &midi, &device_id, 1, ( DWORD_PTR )hwnd, 0, CALLBACK_WINDOW );

Hier ist der Code, um die MIDI -Nachricht zu senden:

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

Wie kann ich dieses Problem lösen?

War es hilfreich?

Lösung

Das Problem war, dass ich die gesamte Ereignisstruktur als Puffer für den MIDI -Stream verwendete. Es stellt sich heraus, dass das vierte Mitglied der Struktur, dwParms, sollte tatsächlich aus Kurznachrichten weggelassen werden. Um den Code in der veröffentlichten Frage zu korrigieren, können zwei der Codezeilen in Folgendes geändert werden:

header.dwBufferLength = sizeof( *event ) - sizeof( event->dwParms );
header.dwBytesRecorded = sizeof( *event ) - sizeof( event->dwParms );

Beim Hinzufügen mehrerer Ereignisse zum Stream ist es tatsächlich viel einfacher, nur ein Array von zu verwenden DWORDs, anstatt sich sogar um das zu kümmern MIDIEVENT Strukturen.

Für alle anderen, die MIDI -Programmierung mithilfe der Windows -API durchführen, achten Sie darauf, dass einige der MSDN -Dokumentation irreführend, unzureichend oder völlig falsch sind.

Die Dokumentation für die MIDIEVENT Struktur sagt Folgendes:

dwparms

Wenn DWEVENT mEVT_F_SHORT angibt, verwenden Sie dieses Mitglied nicht im Stream -Puffer.

Dies ist mehrdeutig, da nicht klar ist, dass "Verwendung" bedeuten soll "eher" "als" angeben ".

Hier sind zwei weitere Fehler in der Dokumentation, von denen Programmierer wissen müssen:

Dwevent

Ereigniscode und Ereignisparameter oder Länge. [...] Das hohe Byte dieses Mitglieds enthält Flags und einen Ereigniscode. Entweder muss das Flag mevt_f_long oder mevt_f_short angegeben werden. Das MEVT_F_Callback -Flag ist optional.

Wenn die Header -Dateien überprüft werden, die MEVT_F_ Präprozessordefinitionen geben tatsächlich vollständig an DWORDs anstatt nur die einzelnen Flags, also hätte in meinem Code in der Frage die Zeile, die dieses Mitglied angibt, wie folgt sein müssen:

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

Darüber hinaus hat sich herausgestellt, dass der Speicher, der die MIDIHDR -Struktur enthält, bis zum Spielen des Puffers beibehalten werden sollte, sodass er für die meisten Implementierungen eher auf dem Haufen als auf dem Stapel zugewiesen werden sollte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top