-
-
Save yoggy/1485181 to your computer and use it in GitHub Desktop.
#include <SDKDDKVer.h> | |
#include <Windows.h> | |
#include <stdio.h> | |
#include <conio.h> | |
#include <mmsystem.h> | |
#pragma comment(lib, "winmm.lib") | |
void PrintMidiDevices() | |
{ | |
UINT nMidiDeviceNum; | |
MIDIINCAPS caps; | |
nMidiDeviceNum = midiInGetNumDevs(); | |
if (nMidiDeviceNum == 0) { | |
fprintf(stderr, "midiInGetNumDevs() return 0..."); | |
return; | |
} | |
printf("== PrintMidiDevices() == \n"); | |
for (unsigned int i = 0; i < nMidiDeviceNum; ++i) { | |
midiInGetDevCaps(i, &caps, sizeof(MIDIINCAPS)); | |
printf("\t%d : name = %s\n", i, caps.szPname); | |
} | |
printf("=====\n"); | |
} | |
void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) | |
{ | |
switch(wMsg) { | |
case MIM_OPEN: | |
printf("wMsg=MIM_OPEN\n"); | |
break; | |
case MIM_CLOSE: | |
printf("wMsg=MIM_CLOSE\n"); | |
break; | |
case MIM_DATA: | |
printf("wMsg=MIM_DATA, dwInstance=%08x, dwParam1=%08x, dwParam2=%08x\n", dwInstance, dwParam1, dwParam2); | |
break; | |
case MIM_LONGDATA: | |
printf("wMsg=MIM_LONGDATA\n"); | |
break; | |
case MIM_ERROR: | |
printf("wMsg=MIM_ERROR\n"); | |
break; | |
case MIM_LONGERROR: | |
printf("wMsg=MIM_LONGERROR\n"); | |
break; | |
case MIM_MOREDATA: | |
printf("wMsg=MIM_MOREDATA\n"); | |
break; | |
default: | |
printf("wMsg = unknown\n"); | |
break; | |
} | |
return; | |
} | |
int main(int argc, char* argv[]) | |
{ | |
HMIDIIN hMidiDevice = NULL;; | |
DWORD nMidiPort = 0; | |
UINT nMidiDeviceNum; | |
MMRESULT rv; | |
PrintMidiDevices(); | |
nMidiDeviceNum = midiInGetNumDevs(); | |
if (nMidiDeviceNum == 0) { | |
fprintf(stderr, "midiInGetNumDevs() return 0..."); | |
return -1; | |
} | |
rv = midiInOpen(&hMidiDevice, nMidiPort, (DWORD)(void*)MidiInProc, 0, CALLBACK_FUNCTION); | |
if (rv != MMSYSERR_NOERROR) { | |
fprintf(stderr, "midiInOpen() failed...rv=%d", rv); | |
return -1; | |
} | |
midiInStart(hMidiDevice); | |
while(true) { | |
if (!_kbhit()) { | |
Sleep(100); | |
continue; | |
} | |
int c = _getch(); | |
if (c == VK_ESCAPE) break; | |
if (c == 'q') break; | |
} | |
midiInStop(hMidiDevice); | |
midiInClose(hMidiDevice); | |
hMidiDevice = NULL; | |
return 0; | |
} |
Windows 10, Codeblock.
Hello thank's for this code. Pehaps could you help me:
i receive callback message for MIM_OPEN, MIM_CLOSE, MIM_DATA but nothing
for MIM_LONGDATA: i tried with a lot of sysex (F0 .. .. .. .. .. .. .. F7) type.
But the issue is not specific to your code and is systematic with every program i buid using midi callback( with codebock or Visual Studio)
Everytime i receive callback message for MIM_OPEN, MIM_CLOSE, MIM_DATA but nothing for MIM_LONGDATA. It's frustrating.
Do you think windows 10 is the problem or other ? Thank in advance for your help
Ignore the above but the Low-level MIDI APIs do work in Win10 perfectly.
If problem persists then try to move the midi functions to a separate file or move the midi functions into a separate thread.
Thanks for pointing to this MIDI C++ code.
The midi_in_sample.cpp
requires some modification to build for 64-bit:
- As reported earlier:
DWORD
toDWORD_PTR
line 75. - It prints only one character of the MIDI port name, because
incaps.szPname
is aWCHAR
type. Replacedprintf
withwprintf
withwhcar.h
include. - Added MIDI output ports in function
PrintMidiDevices()
.
Complete code:
#include <SDKDDKVer.h>
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#include <wchar.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
void PrintMidiDevices()
{
UINT nMidiDeviceNum;
MIDIINCAPS incaps;
MIDIOUTCAPS outcaps;
nMidiDeviceNum = midiInGetNumDevs();
if (nMidiDeviceNum == 0) {
fprintf(stderr, "midiInGetNumDevs() return 0...");
return;
}
printf("MIDI input devices:\n");
for (unsigned int i = 0; i < midiInGetNumDevs(); i++) {
midiInGetDevCaps(i, &incaps, sizeof(MIDIINCAPS));
wprintf(L" %d : name = %s\n", i, incaps.szPname);
}
printf("MIDI output devices:\n");
for (unsigned int i = 0; i < midiOutGetNumDevs(); i++) {
midiOutGetDevCaps(i, &outcaps, sizeof(MIDIINCAPS));
wprintf(L" %d : name = %s\n", i, outcaps.szPname);
}
printf("\n");
}
void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch (wMsg) {
case MIM_OPEN:
printf("wMsg=MIM_OPEN\n");
break;
case MIM_CLOSE:
printf("wMsg=MIM_CLOSE\n");
break;
case MIM_DATA:
printf("wMsg=MIM_DATA, dwInstance=%08x, dwParam1=%08x, dwParam2=%08x\n", dwInstance, dwParam1, dwParam2);
break;
case MIM_LONGDATA:
printf("wMsg=MIM_LONGDATA\n");
break;
case MIM_ERROR:
printf("wMsg=MIM_ERROR\n");
break;
case MIM_LONGERROR:
printf("wMsg=MIM_LONGERROR\n");
break;
case MIM_MOREDATA:
printf("wMsg=MIM_MOREDATA\n");
break;
default:
printf("wMsg = unknown\n");
break;
}
return;
}
int main(int argc, char* argv[])
{
HMIDIIN hMidiDevice = NULL;;
DWORD nMidiPort = 0;
UINT nMidiDeviceNum;
MMRESULT rv;
PrintMidiDevices();
nMidiDeviceNum = midiInGetNumDevs();
if (nMidiDeviceNum == 0) {
fprintf(stderr, "midiInGetNumDevs() return 0...");
return -1;
}
rv = midiInOpen(&hMidiDevice, nMidiPort, (DWORD_PTR)(void*)MidiInProc, 0, CALLBACK_FUNCTION);
if (rv != MMSYSERR_NOERROR) {
fprintf(stderr, "midiInOpen() failed...rv=%d", rv);
return -1;
}
midiInStart(hMidiDevice);
while (true) {
if (!_kbhit()) {
Sleep(100);
continue;
}
int c = _getch();
if (c == VK_ESCAPE) break;
if (c == 'q') break;
}
midiInStop(hMidiDevice);
midiInClose(hMidiDevice);
hMidiDevice = NULL;
return 0;
}
this code works, but do you know if there's any way to make it work while using FL Studio as well? I'd like to have FL Studio running so that I get sound out of it, but want to process the midi input with C++/C# so I can show notes on the staff as I play. if I try to have both programs running at once, neither one works, it gives the "midiInOpen() failed" error.... thanks
To make this work on 64bit, change DWORD to DWORD_PTR on line 75.