| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
mididebugharja 12.07.03 23:29 MIDI-virran käsittelyä Windows-ympäristössä
/* MIDIDebug - pieni MIDI-tiedon debuggaus/muokkausväline Windowsin konsoliin. Suhteellisen vanhaa koodia (pari vuotta vanha) mutta toimii hyvin lähtötason esimerkkinä MIDI-ohjelmointiin */ #include <stdio.h> #include <windows.h> #include <mmsystem.h> #include <mmreg.h> #include <ctype.h> #include <conio.h> #include <string.h> #include <stdlib.h> #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define VERSION "1.1" unsigned char inline HBYTE(const UINT n){return ((n>>8)&0xFF);} // Palauttaa ylimmät 8 bittiä unsigned char inline LBYTE(const UINT n){return (n&0xFF);} // Palauttaa alemmat 8 bittiä unsigned int inline HWORD(const DWORD n){return ((n>>16)&0xFFFF);} // Palauttaa ylimmät 16 bittiä unsigned int inline LWORD(const DWORD n){return (n&0xFFFF);} // Palauttaa alimmat 16 bittiä HMIDIIN hMidiIn; HMIDIOUT hMidiOut; bool printDebug=0; int octave=0,showNotes=0; char* i2b(int n, int bits) // kokonaisluku biteiksi { static char buffer[17]={0}; int i=0, x=0; memset(buffer, 0, 16); while(i<bits) { x=n; x&=0x1; buffer[i++]='0'+x; n>>=1; } buffer[i]='\0'; strrev(buffer); return buffer; } /* Käsittelee sisääntulevan MIDI-datan */ void CALLBACK MidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2) { /* Midi-viesti on paketoitu parametreihin seuraavalla tavalla: Ylempi sana Ylempi tavu - Ei käytössä Alempi tavu - Sisältää toisen tavun MIDI-datasta (tarvittaessa) Alempi sana Ylempi tavu - Ensimmäinen tavu MIDI-datasta (tarvittaessa) Alempi tavu - Itse MIDI data */ int dwH=HWORD(dwParam1),dwL=LWORD(dwParam1); int noteNo=0, Velocity=0, cmd=0, Channel=0, lword=0; char param1High[17]={0}, param1Low[17]={0}, midiDataHigh[9]={0}, midiDataLow[9]={0}, midiStatus[9]={0}; DWORD sendThis=0; strcpy(param1High,i2b(dwH, 16)); strcpy(param1Low,i2b(dwL, 16)); strcpy(midiDataLow, i2b(LBYTE(dwH),8)); strncpy(midiDataHigh, param1Low, 8); strcpy(midiStatus, i2b(LBYTE(dwL),8)); int status=LBYTE(dwL); int midiCmd=(status&0xf0)>>4; sendThis=dwParam1; if(printDebug) printf("MIDI IN: param: %8s %8s status: %8s [0x%x]\n", midiDataHigh, midiDataLow, midiStatus, status); switch(midiCmd) { case 0x8: case 0x9: // Parsitaan data, kuten yllä on kuvattu Velocity=LBYTE(dwH); noteNo=HBYTE(dwL); Channel=(status&0xf)+1; sendThis=0;sendThis=Velocity;sendThis<<=16; noteNo+=(octave*12);lword=noteNo;lword<<=8; lword|=status;sendThis|=lword; if(showNotes) printf("Note %s, no: %d, velocity: %d, channel %d\n", ((Velocity==0||status==0x8)?"off":"on"), noteNo, Velocity, Channel); break; case 0xb: printf("Controller Change, controller number %d, new value %d, channel %d\n", HBYTE(dwL), LBYTE(dwH), status&0x0f); break; case 0xc: printf("Program Change, new patch number %d\n", HBYTE(dwL)); break; case 0xe: printf("Bender Change\n"); break; } midiOutShortMsg(hMidiOut, sendThis); } void CALLBACK MidiOutProc(HMIDIOUT hMidiOut, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { printf("MIDI OUT: Sending message: %d, parameters %ld and %ld\n", wMsg, dwParam1, dwParam2); } void showMidiDevices(void) { int numInDevices=0,numOutDevices=0,i=0,res=0; LPMIDIINCAPS MidiInCaps=new MIDIINCAPS; LPMIDIOUTCAPS MidiOutCaps=new MIDIOUTCAPS; numInDevices=midiInGetNumDevs(); numOutDevices=midiOutGetNumDevs(); if(numInDevices<=0 || numOutDevices<=0) { printf("No available MIDI devices!\n"); exit(EXIT_FAILURE); } printf("\nMIDI In Devices on your system:\n"); printf("-------------------------------\n"); for(i=0;i<numInDevices;i++) { if((res=midiInGetDevCaps(i, MidiInCaps, sizeof(MIDIINCAPS)))!=0) { printf("Error: midiInGetDeviceCaps(): Errno=%d\n",res); exit(EXIT_FAILURE); } printf("MIDI device '%s':\n",MidiInCaps->szPname); printf("\tVersion: %d.%d\n", HBYTE(MidiInCaps->vDriverVersion), LBYTE(MidiInCaps->vDriverVersion)); printf("\twMid: %d ", MidiInCaps->wMid); printf("wPid: %d\n\n", MidiInCaps->wPid); } printf("Midi Out Devices on your system:\n"); printf("--------------------------------\n"); for(i=0;i<numOutDevices;i++) { if((res=midiOutGetDevCaps(i, MidiOutCaps, sizeof(MIDIOUTCAPS)))!=0) { printf("Error: midiOutGetDeviceCaps(): Errno=%d\n",res); exit(EXIT_FAILURE); } printf("MIDI device %d, '%s':\n",i,MidiOutCaps->szPname); printf("\tVersion: %d.%d\n", HBYTE(MidiOutCaps->vDriverVersion), LBYTE(MidiOutCaps->vDriverVersion)); printf("\twMid: %d ", MidiOutCaps->wMid); printf("wPid: %d\n", MidiOutCaps->wPid); printf("\tVoices: %d ", MidiOutCaps->wVoices); printf("Notes: %d\n", MidiOutCaps->wNotes); printf("\tTechnology: "); switch(MidiOutCaps->wTechnology) { case MOD_FMSYNTH: printf("FM Synth\n"); break; case MOD_MAPPER: printf("MIDI Mapper\n"); break; case MOD_MIDIPORT: printf("MIDI Port\n"); break; case MOD_SQSYNTH: printf("Square wave Syntesizer\n"); break; case MOD_SYNTH: printf("Synthesizer\n"); break; default: printf("Unknown\n"); } } delete MidiInCaps; delete MidiOutCaps; } /* Kysytään käyttäjältä mitä laitteita halutaan käyttää */ void selectMidiDevices() { int numInDevices=0,numOutDevices=0,i=0, selin=-1,selout=-1,res=0; DWORD volume=0; LPMIDIINCAPS MidiInCaps=new MIDIINCAPS; LPMIDIOUTCAPS MidiOutCaps=new MIDIOUTCAPS; numInDevices=midiInGetNumDevs(); numOutDevices=midiOutGetNumDevs(); if(numInDevices>1) while(selin<0){printf("\nSelect Input Interface: "); scanf("%d", &selin);} else selin=0; if(numOutDevices>1) while(selout<0){printf("\nSelect Output Interface: "); scanf("%d", &selout);} else selout=0; if(midiInGetDevCaps(selin, MidiInCaps, sizeof(MIDIINCAPS))!=0){printf("Error (%d)!\n", selin); exit(EXIT_FAILURE);} printf("Opening midi in device %d, '%s'...\n", selin, MidiInCaps->szPname); if((res=midiInOpen(&hMidiIn, selin, (unsigned long)&MidiInProc, NULL, CALLBACK_FUNCTION))) { char buffer[255]; midiInGetErrorText(res,buffer,255); printf("Error opening midi in '%s'\n %s!\n", MidiInCaps->szPname, buffer); exit(EXIT_FAILURE); } midiInStart(hMidiIn); printf("Midi Input port opened... listening.\n"); if(midiOutGetDevCaps(selout, MidiOutCaps, sizeof(MIDIOUTCAPS))!=0){printf("Error (%d)!\n", selout); exit(EXIT_FAILURE);} printf("Opening midi out device %d, '%s'...\n", selout, MidiOutCaps->szPname); if((res=midiOutOpen(&hMidiOut, selout, (ULONG)&MidiOutProc, NULL, CALLBACK_FUNCTION))) { char buffer[255]; midiInGetErrorText(res,buffer,255); printf("Error opening midi out '%s'\n %s!\n", MidiOutCaps->szPname, buffer); exit(EXIT_FAILURE); } midiOutGetVolume(hMidiOut,&volume); printf("Midi Out port opened, volume L=%d%% R=%d%%...\n",(int)(((float)HWORD(volume)/(float)0xFFFF)*100.0),(int)(((float)LWORD(volume)/(float)0xFFFF)*100.0)); delete MidiOutCaps; delete MidiInCaps; } void shutDown(void) { midiInStop(hMidiIn); midiInClose(hMidiIn); midiOutClose(hMidiOut); } /* Ohjelmaan päälooppi */ void mainLoop() { int numInDevices=0,numOutDevices=0,i=0, selin=-1,selout=-1,res=0; DWORD volume=0; char ch=0; while(ch!=27) { ch=_getch(); if(ch=='p') { int newpatch=-1; DWORD dwParam=0; while(newpatch<0) { fflush(stdin); printf("new patch number: "); scanf("%d",&newpatch); } dwParam=newpatch; dwParam<<=8; dwParam|=192; int err=midiOutShortMsg(hMidiOut, dwParam); } else if(ch=='v') { int volume=-1; DWORD dwVolume=0; while(volume<0) { fflush(stdin); printf("new volume (in percentage): "); scanf("%d",&volume); } volume=(int)(((float)volume/100.0)*(float)0xFFFF); printf("Volume=%d\n", volume); dwVolume=volume; dwVolume<<=16; dwVolume|=volume; midiOutSetVolume(hMidiOut, dwVolume); printf("Volume set to: L=%d%% R=%d%%\n", (int)(((float)HWORD(dwVolume)/(float)0xFFFF)*100.0),(int)(((float)LWORD(dwVolume)/(float)0xFFFF)*100.0)); } else if(ch=='m') { printDebug=!printDebug; printf("Debugging %s\n", printDebug?"enabled":"disabled"); } else if(ch=='h') { printf("KEYBOARD HELP\n"); printf("-------------\n"); printf("p Change the patch\n"); printf("v Change the volume\n"); printf("+ Add an octave to the original note\n"); printf("- Remove an octave from the original note\n"); printf("* Reset the octave to 0\n"); printf("s Show/do not show MIDI note on/off commands\n"); printf("m Print Debug Information\n"); printf("d Print devices\n"); printf("c Change devices\n"); printf("q or ESC Exit the program\n"); } else if(ch=='d') { showMidiDevices(); } else if(ch=='c') { shutDown(); selectMidiDevices(); } else if(ch=='s') { showNotes=(showNotes==1?0:1); printf("Showing notes %s\n", ((showNotes==1)?"enabled":"disabled")); } else if(ch=='+') { octave++; printf("Octave + 1 = %d\n", octave); } else if(ch=='-') { octave--; printf("Octave - 1 = %d\n", octave); } else if(ch=='*') { octave=0; printf("Octave reset to 0\n"); } else if(ch=='q') ch=27; } } int main(void) { printf(".----------------------------------------------.\n"); printf("|MIDI Debugger version %3s (c) Mikko Harju 2001|\n",VERSION); printf(".______________________________________________|.\n"); showMidiDevices(); selectMidiDevices(); mainLoop(); shutDown(); return 0; } |
![]() Haku
|