본문

midi-dot-net 으로 MIDI 컨트롤 메시지 발생시키기

처음에는 VMPK와 RtMIDI 라이브러리를 사용한 프로젝트를 구상하였으나, 이미 메인 언어를 c#.net으로 정하고 일부 모듈을 만들었기에 위 둘은 그냥 참고사항정도로 넘기고 대신 .net 기반의 MIDI 프로젝트에 대해서 찾아보기로 했다. 검색하자마자 나온것이 midi-dot-net 이고 이는 매우 보기 쉽고 간단한 구조로 추상화 되어있어 이것을 사용하기로 마음먹었다. 원하는 기능인 메시지 발생하는 부분도 잘 정리되어있어 그 소스를 여기에 가져온다. 압축된 소스파일내의 Example2.cs의 68번째 줄에있는 Run()에서 추려낸 필요한 부분을 살펴본다.

// ChooseOutputDeviceFromConsole으로 필요한 출력장치를 불러오고 준비한다.
OutputDevice outputDevice = ExampleUtil.ChooseOutputDeviceFromConsole();
outputDevice.Open();

// Sustain 페달을 누른다.
outputDevice.SendControlChange(Channel.Channel1, Control.SustainPedal, 127);

 // 0.5초 간격으로 도, 미, 솔 음을 발생시킨다.
outputDevice.SendNoteOn(Channel.Channel1, Pitch.C4, 80);
Thread.Sleep(500);
outputDevice.SendNoteOn(Channel.Channel1, Pitch.E4, 80);
Thread.Sleep(500);
outputDevice.SendNoteOn(Channel.Channel1, Pitch.G4, 80);
Thread.Sleep(500);

// 음높이(Pitch)를 낮춘다
for (int i = 0; i < 17; ++i)
{
outputDevice.SendPitchBend(Channel.Channel1, 8192 - i * 450);
Thread.Sleep(200);
}

// Sustain 페달을 떼고, 다시 원래상태로 음높이를 조절한다.
outputDevice.SendControlChange(Channel.Channel1, Control.SustainPedal, 0)
outputDevice.SendPitchBend(Channel.Channel1, 8192);

 // 장비를 정지합니다..
outputDevice.Close();


그리고 아래에는 위에있던 ChooseOutputDeviceFromConsole()의 내용이다. 즉 장치가 없을경우 null, 하나 있을때는 하나에 대한 장치정보, 그리고 여럿있을때에는 그중 하나를 선택하도록 하는것이다.

public static OutputDevice ChooseOutputDeviceFromConsole()
{
if (OutputDevice.InstalledDevices.Count == 0)
{
return null;
}
if (OutputDevice.InstalledDevices.Count == 1) {
return OutputDevice.InstalledDevices[0];
}
Console.WriteLine("Output Devices:");
for (int i = 0; i < OutputDevice.InstalledDevices.Count; ++i)
{
Console.WriteLine(" {0}: {1}", i, OutputDevice.InstalledDevices[i].Name);
}
Console.Write("Choose the id of an output device...");
while (true)
{
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
int deviceId = (int)keyInfo.Key - (int)ConsoleKey.D0;
if (deviceId >= 0 && deviceId < OutputDevice.InstalledDevices.Count)
{
return OutputDevice.InstalledDevices[deviceId];
}
}
}



이게 전부다. 단 컨트롤 메시지를 보낼때 사용하는 메소드는 public void SendControlChange(Channel channel, Control control, int value) 으로 정의되어있고, Control은 enum으로 정의되어있기때문에 임의의 값을 집어넣지 못한다. 같이 제공되는 dll파일로 편하게 쓰려 했지만 이거 하나가 걸리네... 그래도 수정해서 다시 만들면 되니 이정도면 충분히 만족한다

댓글

Holic Spirit :: Tistory Edition

design by tokiidesu. powerd by kakao.