Question

J'écris un programme Windows en C ++ et l'API Windows, et essaie de la file d'attente des messages MIDI dans un flux MIDI, mais je reçois une étrange erreur lorsque je tente de le faire. Si j'utilise midiOutShortMsg pour envoyer un message MIDI non mis en attente au flux, il fonctionne correctement. Cependant, midiStreamOut renvoie toujours le code d'erreur 68, qui est #defined à MCIERR_WAVE_OUTPUTUNSPECIFIED. midiOutGetErrorText donne la description suivante de l'erreur:

  

La configuration actuelle du mappeur MIDI fait référence à un appareil MIDI qui n'est pas installé sur le système. Utilisez mappeur MIDI pour modifier la configuration.

J'utilise Windows 7 (64 bits) et ont essayé d'ouvrir le flux MIDI avec des ID de périphériques des deux MIDI_MAPPER et les quatre périphériques de sortie MIDI sur mon système, et continue de recevoir exactement le même message d'erreur.

Voici le code pour ouvrir le flux MIDI:

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

Voici le code pour envoyer le message 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 ) );

Comment puis-je résoudre ce problème?

Était-ce utile?

La solution

Le problème était que j'utilisais la structure complète d'un événement comme le tampon pour le flux MIDI. Il se trouve que le quatrième membre de la structure, dwParms, devrait effectivement être omis de messages courts. Pour corriger le code de la question posée, deux des lignes de code pourrait être changé à ce qui suit:

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

Lors de l'ajout de plusieurs événements dans le flux, il est en fait beaucoup plus facile à utiliser juste un tableau de DWORDs plutôt que de prendre la peine même avec les structures MIDIEVENT.

Pour quelqu'un d'autre faire la programmation MIDI en utilisant l'API Windows, méfiez-vous que certains des documents MSDN est trompeur, inadéquat ou complètement faux.

La documentation de la structure MIDIEVENT dit ce qui suit:

  

dwParms

     

Si dwEvent spécifie MEVT_F_SHORT, ne pas utiliser ce membre dans la mémoire tampon de flux.

Ceci est ambigu car il est clair que « utilisation », on entend « inclure » plutôt que « préciser ».

Voici deux autres failles dans la documentation que les programmeurs doivent être conscients de:

  

dwEvent

     

Code de l'événement et des paramètres d'événement ou de la longueur. [...] L'octet de poids fort de ce membre contient des drapeaux et un code d'événement. Soit doit être spécifié le drapeau MEVT_F_LONG ou MEVT_F_SHORT. Le drapeau de MEVT_F_CALLBACK est facultative.

Lorsque les fichiers d'en-tête sont vérifiés, les définitions de préprocesseur MEVT_F_ spécifient réellement DWORDs complets plutôt que les drapeaux individuels, donc dans mon code dans la question, la ligne spécifiant ce membre aurait dû être comme suit:

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

En plus de cela, il est également avéré que la mémoire contenant la structure MIDIHDR doit être conservée jusqu'à ce que le tampon a fini de jouer, il devrait donc être alloué sur le tas plutôt que la pile pour la plupart des implémentations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top