Domanda

Sto scrivendo un programma per Windows utilizzando C ++ e l'API di Windows, e, sto cercando di fare la coda messaggi MIDI in un flusso MIDI, ma sto ricevendo uno strano errore quando provo a farlo. Se uso midiOutShortMsg per inviare un messaggio non in coda MIDI al flusso, funziona correttamente. Tuttavia, midiStreamOut restituisce sempre il codice di errore 68, che è #defined a MCIERR_WAVE_OUTPUTUNSPECIFIED. midiOutGetErrorText ha pronunciato la seguente descrizione dell'errore:

  

L'impostazione corrente di MIDI Mapper si riferisce ad un dispositivo MIDI che non è installato nel sistema. Utilizzare MIDI Mapper per modificare l'impostazione.

Sto usando Windows 7 (64-bit) e ho provato l'apertura del flusso MIDI con gli ID dei dispositivi sia MIDI_MAPPER e tutti e quattro i dispositivi di uscita MIDI sul mio sistema, e continuare a ricevere il messaggio di errore esattamente lo stesso.

Ecco il codice per aprire il flusso MIDI:

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

Ecco il codice per inviare il messaggio 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 ) );

Come posso risolvere questo problema?

È stato utile?

Soluzione

Il problema era che stavo usando l'intera struttura evento come il buffer per il flusso MIDI. Risulta che il quarto membro della struttura, dwParms, effettivamente deve essere omesso dai messaggi brevi. Per correggere il codice in questione Postato, due delle righe di codice potrebbe essere modificato al seguente:

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

Quando si aggiungono più eventi al flusso, in realtà è molto più facile da usare solo una serie di DWORDs piuttosto che nemmeno preoccuparsi con le strutture MIDIEVENT.

Per chiunque altro a fare la programmazione MIDI utilizzando l'API di Windows, fate attenzione che alcune parti della documentazione MSDN è fuorviante, inadeguata o del tutto sbagliato.

La documentazione per la struttura MIDIEVENT dice quanto segue:

  

dwParms

     

Se dwEvent specifica MEVT_F_SHORT, non utilizzare a questo utente nel buffer di flusso.

Questa è ambigua perché non è chiaro che "usa" è destinato a significare "include" piuttosto che "specificare".

Ecco altri due difetti nella documentazione che i programmatori hanno bisogno di essere a conoscenza di:

  

dwEvent

     

Codice Evento e parametri di evento o la lunghezza. [...] Il byte alto di questo membro contiene bandiere e un codice evento. O deve essere specificato il flag MEVT_F_LONG o MEVT_F_SHORT. La bandiera MEVT_F_CALLBACK è facoltativo.

Quando i file header vengono controllati, le definizioni del preprocessore MEVT_F_ effettivamente specificano DWORDs completi piuttosto che solo i singoli bandiere, così nel mio codice nella questione, la linea specifica a questo utente avrebbe dovuto essere il seguente:

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

In aggiunta a questo, ha anche scoperto che la memoria contenente la struttura MIDIHDR dovrebbe essere mantenuta finché il buffer termina la riproduzione, quindi dovrebbe essere assegnato in mucchio anziché stack per la maggior parte delle implementazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top