Created
December 16, 2011 08:46
-
-
Save yoggy/1485181 to your computer and use it in GitHub Desktop.
MIDI-in sample program for Win32 (using winmm.lib)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ignore the above but the Low-level MIDI APIs do work in Win10 perfectly.