Pregunta

Estoy escribiendo un programa de Windows con C++ y la API de Windows, y, estoy tratando de cola de mensajes MIDI en una secuencia de MIDI, pero estoy recibiendo un extraño error cuando trato de hacerlo.Si yo uso midiOutShortMsg para enviar un no a la cola de mensajes MIDI a la corriente, funciona correctamente.Sin embargo, midiStreamOut siempre devuelve el código de error 68, que es #defined a MCIERR_WAVE_OUTPUTUNSPECIFIED. midiOutGetErrorText da la siguiente descripción del error:

La actual configuración de Mapeador MIDI se refiere a un dispositivo MIDI que no está instalado en el sistema.El uso de MIDI Mapper para modificar la configuración.

Estoy usando Windows 7 (64-bit) y han intentado abrir la secuencia de MIDI con los Id de dispositivo de ambos MIDI_MAPPER y todos los cuatro dispositivos de salida MIDI en mi sistema, y sigue recibiendo el mismo mensaje de error.

Aquí está el código para abrir la secuencia de MIDI:

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

Aquí está el código para enviar el mensaje 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 ) );

¿Cómo puedo resolver este problema?

¿Fue útil?

Solución

El problema era que estaba usando toda la estructura de eventos como el búfer para la secuencia de MIDI.Resulta que el cuarto miembro de la estructura, dwParms, en realidad debería ser omitido de mensajes cortos.Para corregir el código en el publicado pregunta, dos de las líneas de código puede ser modificado de la siguiente manera:

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

Cuando la adición de múltiples eventos en la secuencia, de hecho es mucho más fácil usar una matriz de DWORDs más que siquiera se molesta con el MIDIEVENT estructuras.

Para cualquier otra persona haciendo la programación MIDI usando el API de Windows, ten en cuenta que algunos de la documentación de MSDN es engañosa, insuficiente o completamente equivocado.

La documentación de la MIDIEVENT estructura dice lo siguiente:

dwParms

Si dwEvent especifica MEVT_F_SHORT, no utilice este miembro en el búfer de secuencia.

Este es ambiguo porque no está claro que el "uso" significa "incluir" en lugar de "especificar".

Aquí hay dos errores en la documentación que los programadores deben ser conscientes de:

dwEvent

Código de evento y los parámetros de evento o de longitud.[...] El byte alto de este miembro contiene indicadores y un código de evento.El MEVT_F_LONG o MEVT_F_SHORT bandera debe ser especificado.El indicador MEVT_F_CALLBACK es opcional.

Cuando el encabezado de los archivos se comprueban, la MEVT_F_ las definiciones del preprocesador en realidad especificar completa DWORDs en lugar de sólo los marcadores individuales, por lo que en mi código en la pregunta, la línea de la especificación de este miembro debe de haber sido el siguiente:

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

Además de esto, también se ha convertido en la memoria que contiene la estructura MIDIHDR deben ser retenidos hasta que el buffer se ha terminado de jugar, por lo que debe ser asignado en el montón en lugar de la pila para la mayoría de las implementaciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top