INPUTデバイスとOUTPUTデバイスを開いて、INPUTデバイスから入力があったらそのままOUTPUTデバイスに流す。
EDIROL PC-50の場合、NOTE OFF は使わずにベロシティ0のNOTE ONを使うらしい。
PC-50とTHRUプログラム間はランニングステータスを使って1バイト削減してるのではなかろうか。
THRUプログラムとOUTPUT間はランニングステータスを使わずにきっちり4バイト送ってる。
INPUTのコールバックから直接OUTPUTに送るために、グローバル変数を使ってしまった。
クラスを作れないC言語の場合、どうするのが推奨されてるんだろう。
ソース
#pragma comment(lib, "winmm.lib") #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <mmsystem.h> HMIDIOUT hmo; HMIDIIN hmi; /* DEVICE LIST */ void list_input_devices() { int num, id, i; char pname[65]; num = midiInGetNumDevs(); printf("INPUT : %d\n", num); for(id=0; id<num; id++){ MIDIINCAPS in; midiInGetDevCaps(id, &in, sizeof(in)); memset(&pname, '\0', sizeof(pname)); for (i=0; i<sizeof(pname); i++) { memcpy(pname+i, in.szPname+i, 1); } printf("[%d] %s\n", id, pname); } } void list_output_devices() { int num, id, i; char pname[65]; num = midiOutGetNumDevs(); printf("OUTPUT : %d\n", num); for(id=0; id<num; id++){ MIDIOUTCAPS out; memset(&out, '\0', sizeof(out)); midiOutGetDevCaps(id, &out, sizeof(out)); memset(&pname, '\0', sizeof(pname)); for (i=0; i<sizeof(pname); i++) { memcpy(pname+i, out.szPname+i, 1); } printf("[%d] %s\n", id, pname); } } /* INPUT CALLBACK */ void CALLBACK MidiInProc(HMIDIIN hmi, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { switch (wMsg) { case MIM_DATA: case MIM_LONGDATA: printf("MidiInProc: wMsg=%08X, p1=%08X, p2=%08X\n", wMsg, dwParam1, dwParam2); midiOutShortMsg(hmo, dwParam1); break; } } /* INPUT DEVICE */ int deviceInOpen(HMIDIIN *hmi, UINT deviceno) { if (midiInOpen(hmi, deviceno, (DWORD_PTR)MidiInProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) { return -1; } return 0; } int deviceInClose(HMIDIIN *hmi) { if (midiInClose(*hmi) != MMSYSERR_NOERROR) { return -1; } return 0; } /* OUTPUT DEVICE */ int deviceOutOpen(HMIDIOUT *hmo, UINT deviceno) { if (midiOutOpen(hmo, deviceno, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) { return -1; } return 0; } int deviceOutClose(HMIDIOUT *hmo) { if (midiOutClose(*hmo) != MMSYSERR_NOERROR) { return -1; } return 0; } /* MAIN */ int main(void) { int scan; int ret; int input_ok = 0; int output_ok = 0; list_input_devices(); printf("\n"); list_output_devices(); printf("\n"); // ポインタとデバイスIDを渡してMIDI INデバイスを開く while (input_ok==0) { printf("Enter input device number: "); ret = scanf_s("%d", &scan); if (ret==0) { while (getchar() != '\n'){} continue; } if (deviceInOpen(&hmi, scan) < 0) { printf("MIDI INデバイスオープン失敗\n"); } else { input_ok = 1; } } printf("Input device ready.\n\n"); // ポインタとデバイスIDを渡してMIDI OUTデバイスを開く while (output_ok==0) { printf("Enter output device number: "); ret = scanf_s("%d", &scan); if (ret==0) { while (getchar() != '\n'){} continue; } if (deviceOutOpen(&hmo, scan) < 0) { printf("MIDI OUTデバイスオープン失敗\n"); } else { output_ok = 1; } } printf("Output device ready.\n\n"); printf("--------------------\n"); printf("Devices ready.\n"); printf("--------------------\n"); // 入力開始 midiInStart(hmi); while (1) { Sleep(100); } // 入力停止 midiInStop(hmi); midiInReset(hmi); // ポインタを渡してMIDI OUTデバイスを閉じる deviceOutClose(&hmo); // ポインタを渡してMIDI INデバイスを閉じる deviceInClose(&hmi); return 0; }