본문 바로가기
코딩/잡다한 C언어

C언어로 Midi 입력을 받는 코드 만들기

by jsjin 2023. 5. 24.
728x90

(Midi에 대한 더 자세한 정보를 확인하려면 Midi 공식문서인 https://www.midi.org/specifications를 참고)

 

코드를 짜기 전에 특정 라이브러리를 링크해야 한다.

1.     Visual Studio에서 프로젝트를 연다.

2.     솔루션 탐색기(단축키: Ctrl + Alt + L)을 눌러 프로젝트에 우클릭 후 속성을 선택한다.

3.     구성 속성에 들어가 링커를 선택하고 입력을 선택한다.

4.     추가 중속성 상자에 ‘winmm.lib’를 입력한다.

 

코드는 다음과 같다.

#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>

// MIDI 입력 콜백 함수
void CALLBACK MidiInputCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
    if (wMsg == MIM_DATA) {
        BYTE status = (dwParam1 & 0xFF);
        BYTE data1 = (dwParam1 >> 8) & 0xFF;
        BYTE data2 = (dwParam1 >> 16) & 0xFF;

        // MIDI 메시지 출력
        printf("Status: %02X, Data1: %02X, Data2: %02X\n", status, data1, data2);
    }
}

int main() {
    HMIDIIN hMidiIn;
    MMRESULT result;

    // MIDI 입력 장치 개수 확인
    UINT numDevices = midiInGetNumDevs();
    printf("MIDI devices found : %d\n", numDevices);
    if (numDevices == 0) {
        printf("No MIDI input devices found.\n");
        return 1;
    }
    
    // MIDI 입력 장치 열기
    result = midiInOpen(&hMidiIn, 0, (DWORD_PTR)MidiInputCallback, 0, CALLBACK_FUNCTION);
    if (result != MMSYSERR_NOERROR) {
        printf("Failed to open MIDI input device.\n");
        return 1;
    }

    // MIDI 입력 시작
    result = midiInStart(hMidiIn);
    if (result != MMSYSERR_NOERROR) {
        printf("Failed to start MIDI input.\n");
        midiInClose(hMidiIn);
        return 1;
    }

    printf("Listening for MIDI input. Press Enter to exit.\n");
    getchar(); // enter 입력 받기

    // MIDI 입력 중지
    midiInStop(hMidiIn);
    midiInClose(hMidiIn);

    return 0;
}

 

MidiInputCallback 함수는 Midi 장치로 부터 발생한 이벤트를 받기 위한 콜백 함수이다.

이 함수는 Midi 메시지가 수신되었을 때 호출된다.

 

함수의 매개변수에 대해 설명하면:

hMidiIn: MIDI 입력 장치의 핸들이며, 이를 통해 특정 MIDI 입력 장치를 식별 및 제어한다.

 

wMsg: MIDI 입력 이벤트의 유형을 나타내는 메시지이다. MIDI 데이터 메시지를 수신할 때 이 메시지가 전달된다.

 

dwInstance: MIDI 입력 콜백 함수에 전달된 사용자 정의 인스턴스 데이터이다. MIDI 입력 장치를 열 때 콜백 함수와 연결된 데이터를 지정한다.

 

dwParam1, dwParam2: MIDI의 상태(status), 데이터1(data1), 데이터2(data2)가 포함된다.

 

 

MIDI 데이터는 24비트의 값을 가진다.

8비트는 상태(키보드를 눌렀는가? 아닌가?)

다음 8비트는 계이름을 의미하는 데이터,

마지막 8비트는 누르는 세기를 의미한다.

if (wMsg == MIM_DATA) {
        BYTE status = (dwParam1 & 0xFF);
        BYTE data1 = (dwParam1 >> 8) & 0xFF;
        BYTE data2 = (dwParam1 >> 16) & 0xFF;

        // MIDI 메시지 출력
        printf("Status: %02X, Data1: %02X, Data2: %02X\n", status, data1, data2);
        }

따라서 status에 MIDI의 상태값을 16진수로 변환하여 저장한다.

data1에 MIDI 데이터의 8비트 뒤에 위치한 계이름에 관한 비트를 16진수로 변환하여 저장한다.

data2에 MIDI 데이터의 16비트 뒤에 위치한 세기에 관한 비트를 16진수로 변환하여 저장한다.

 

16진수로 변환하는 이유는 . MIDI 메시지의 값은 보통 0부터 127까지이기에 이를 16진수로 표현하면 00부터 7F까지의 범위로 표현할 수 있기 때문이다.

보기 편하기 위해 16진수를 쓰는 것이기에, 어떠한 진수를 사용해도 상관없다.

 

 

MIDI 입역 장치 개수 확인

midiInGetNumDevs();

이 함수를 사용하면 연결되어 있는 미디 장치의 개수를 반환한다.

 

 

MIDI 입력 장치 열기 & 입력 시작

MIDI 입력 장치는 midiInOpen 함수를 사용해 열 수 있다.

MMRESULT midiInOpen(
  LPHMIDIIN phmi,
  UINT      uDeviceID,
  DWORD_PTR dwCallback,
  DWORD_PTR dwInstance,
  DWORD     fdwOpen
);

매개 변수에 대해 설명하면:

lphMidiIn: MIDI 입력 장치의 핸들을 받을 포인터 주소이다.

 

uDeviceID: MIDI 입력 장치의 인덱스 또는 식별자 -> 값이 0 = 인덱스 0에 해당하는 MIDI 입력 장치

 

dwCallback: MIDI 콜백 함수의 주소. MIDI 입력 메시지가 발생할 때마다 콜백 함수가 호출된다.

 

dwCallbackInstance: MIDI 입력 콜백 함수에 전달되는 데이터. 콜백 함수에서 이 값을 활용 가능하다.

 

fdwOpen: MIDI 입력 장치의 동작 옵션을 설정하는 플래그. 주로 0 또는 CALLBACK_FUNCTION 값을 사용하며, CALLBACK_FUNCTION은 콜백 함수가 함수 포인터로 정의되어 있음을 의미한다.

 

if (result != MMSYSERR_NOERROR) {
	printf("Failed to start MIDI input.\n");
	midiInClose(hMidiIn);
	return 1;
}

MMSYSERR_NOERROR는 멀티미디어 시스템 함수가 성공적으로 수행되었음을 의미한다.

따라서 위의 코드는 MIDI 연결이 실패하거나 입력 시작 과정에서 문제가 발생시 오류를 알려준다.

 

 

MIDI 입력 중지

midiInStop(hMidiIn) 함수는 MIDI 입력을 중지한다.

midiInClose(hMidiIn) 함수는 MIDI 입력 장치를 닫는다.

728x90