2021년 2월 24일 수요일

파이썬으로 구현한 서스테인 페달

이전에 쓴 글 '[우분투의 사운드와 MIDI] 스페이스 바를 서스테인 페달 대용으로 쓰게 만드는 파이썬 프로그램'에서 소개했던 방법을 개선해 보았다. 신호를 보낼 MIDI OUT 포트(즉 음원)를 스크립트 내에 써 넣지 않아도 되게 만든 것이다. FluidSynth를 구동한 뒤 MIDI 키보드 콘트롤러와 연결(aconnect)하고 나서 다음과 같은 bash script("sustain-pedal.sh")를 실행을 하면 된다.

#!/usr/bin/env bash

script=$(readlink -f "$0")
path=$(dirname "$script")

OIFS=$IFS; IFS=$'\n'
array=($(sendmidi list)); IFS=$OIFS

i=0
for var in "${array[@]}"
do
    echo "[$i] ${var}"
    i=`expr $i + 1`
done
echo -n "Select MIDI OUT device: "
read -r input
midi_out=${array[$input]}
python ${path}/sustain-pedal.py ${midi_out}

이 스크립트는 이전에 만든 sustain-pedal.py이라는 파이썬 스크립트를 부른다. 이는 pygame이라는 모듈이 필요하다. 아래에서 보인 이 파이썬 스크립트는 또 sendmidi라는 프로그램를 내부에서 실행하므로 이를 설치해 두어야 한다. 명령행 인수를 받을 수 있도록 조금 수정을 가했다. 내부에서 sendmidi를 실행하는 명령어 문자열도 약간 세련되어 보이게 고쳤다.

import pygame
import time
import os
import sys

pygame.init()
d = pygame.display.set_mode((800,600))
d.fill((255,255,255))

sendmidi = "/home/hyjeong/bin/sendmidi";
pedal_on = "%s dev %s cc 64 127"%(sendmidi, sys.argv[1]);
pedal_off = "%s dev %s cc 64 0"%(sendmidi, sys.argv[1]);

done = False
while not done:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      done = True
    if event.type == pygame.KEYDOWN:
      print("Got keydown event: " + str(event))
      os.system(pedal_on)
    if event.type == pygame.KEYUP:
      print("Got keyup event: " + str(event))
      os.system(pedal_off)

pygame.quit()
quit()

그러면 일종의 wrapper script인 sustain-pedal.sh을 실행해 보자.

$ sustain-pedal.sh 
[0] Midi Through Port-0
[1] iCON iKeyboard 5 Nano V1.06 MID
[2] Synth input port (3627:0)
Select MIDI OUT device: 2
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html

번호를 입력하여 MIDI 신호를 보낼 synthesizer를 지정하면 곧바로 커다란 창이 뜬다. 마우스 포인터는 그 안에 위치할 것이다. 그 다음에는 보통의 서스테인 페달을 밟듯이 아무 키나 누르면 된다. 한번에 여러 키를 누르면 제각각 페달 신호를 보내면서 상태가 꼬이기 쉬우니 발가락으로 요령껏 스페이스바를 눌렀다 떼었다 하는 것이 좋을 것이다. 마우스 포인터가 검정 창 안에 있으므로 키보드를 조작하는 것으로는 실행 중인 다른 프로그램을 건드리지는 않는다.

 



 
그다지 아름답지는 않지만 이런 방식으로...

리눅스에서는 눌렀던 키를 릴리즈하는 이벤트를 프로그램으로 구현하는 것이 어려움을 설명한 글의 링크가 서두에 소개한 이전 글에 들어 있다. 그래서 게임 개발에 쓰이는 파이썬 모듈을 활용한 것이다. 게임에서는 눌렀던 키를 릴리즈하는 동작을 인식하는 것이 대단히 중요할 테니까.

예전 방법에서는 sendmidi 명령을 다음과 같이 주어야 하는 것이 너무나 귀찮았다.

sendmidi dev 'SC-D70 Part A' cc 64 127

이것은 사운드캔버스 SC-D70이 연결되었을 때의 방법이다. 다른 오디오 인터페이스를 쓰려면 파라미터를 바꾸어야 한다. 소스 코드를 매번 바꾸어야 한다는 뜻이다. 그래서 오늘 '개발(?)'한 방법에서는 wrapper script를 통해 'sendmidi list'를 먼저 실행하여 MIDI 출력 포트 목록을 화면에 번호와 함께 나오게 한 다음, 번호를 입력하여 원하는 것을 지정하게 만들었다. Here document를 써서 파이썬 코드를 bash 내에 넣어버릴 수도 있는데, 그러한 경우 인수 또는 변수를 내부에서 전달하는 방법까지는 아직 잘 모르겠다. 이는 다음을 위한 숙제로 남겨 두자.

두꺼운 종이나 나뭇조각을 이용하여 밟았을 때 스페이스 바만 눌리게 하는 도구를 만들어도 되겠다.


댓글 없음: