2026년 1월 17일 토요일

Nano Ardule의 MIDI 파일 재생 기능 개선

Nano Ardule의 펌웨어 개발이 이제 대부분의 기능 구현을 마쳤고 리팩토링 단계에 접어들었다고 바로 이전 글에서 호기롭게 선언하였지만, 아직 모든 것이 완벽하지는 않다. 가장 불편하다고 느끼는 것은 일반적인 type 0 MIDI file을 재생할 때 시작 부분에서 음이 와르르 쏟아지듯 들리는 것이다. 시작 포인트를 약간 지나서 음이 밀려서 쏟아져 나오면서 음 간격은 정상보다 더 좁게 느낀다. 다음 동영상(FLOURISH.MID)에서 첫번째 것이 코드 수정 전의 상태이다. 녹음이 썩 깨끗하게 되지는 않았지만 귀를 기울여 들어보면 뭔가 자연스럽지 않다는 것을 알 수 있다. 이후 두 번의 녹음은 한결 나아진 모습을 보인다.



이 현상을 'Starting Burst'라 부르기로 하고 원인 분석 및 해결에 나서기로 했다. 비상용 (드럼) 패턴이나 단일 패턴 재생에서는 관찰되지 않는다. 녹음한 사운드를 챗GPT에 업로드하여 분석을 실시하고, 이로부터 해결 방안을 도출하여 코드를 수정하는 사이클을 두 차례 걸쳤다. 문제의 원인은 타이밍 스케쥴링 에 있다고 판단하였다. 구체적인 원인 분석과 개선 전략은 별도의 글에 정리하였다. 완벽하게 문제가 해결되었다고 볼 수는 없으나, 실용적인 면에서는 이것으로 충분하다. 이 펌웨어는 type 0 MIDI 파일 재생을 목표로 하는 것이 아니기 때문이다. 드럼 전용 패턴 또는 ARR 파일의 재생은 아주 매끄럽게 잘 되고 있다.

만약 아두이노용 MIDI 라이브러리를 사용하여 펌웨어 개발을 했다면 이런 문제를 겪지 않았을지도 모른다. 그러나 그만큼 더 많은 메모리 공간이 필요하고, 내가 원하는 기능까지 넣는 것은 불가능하다고 판단하였었다. 그래서 다음과 같은 것이 전부 내가 만드는 펌웨어의 몫이었다.

  • MIDI 파일 파싱(VLQ, running status, meta event)
  • tick -> time 변환
  • 스케쥴러(catch-up, drift, blocking)
  • SD/IO의 블로킹 특성
  • MCU 타이밍(마이크로초/밀리초 해상도)

MIDI와 관련된 라이브러리를 전혀 사용하지 않은 '날것 코딩'을 선택하였기 때문에 MIDI 파일을 일단 재생하게 만드는 것조차 쉽지 않았다. 그러나 더욱 강력한 통제력을 얻을 수 있었다. 문제의 원인을 정확히 진단하고, 실용적으로 문제가 느껴지지 않는 수준까지(만) 개선하는 것. 충분히 합리적인 자세였다고 자체 판단하기로 했다.

몇 시간 지난 후 재평가를 해 보았다. 아직도 약간의 지연이 느껴져서 재생 시작 시 200 msec의 고정 지연 시각을 주었더니 훨씬 나아진 것 같다.

가끔 git push를 하다가 다음과 같은 메시지를 접하고 놀랄 때가 있다.

> git push
To https://github.com/jeong0449/NanoArdule.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/jeong0449/NanoArdule.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

README.md 같은 것을 GitHub 웹사이트에서 직접 고쳐 놓은 다음 로컬에 이를 반영하지 않은 상태에서 다른 파일을 고친 뒤 push를 하려다가 이런 일을 겪는다. 이때에는 'git pull origin main'(= git pull, 조건이 맞는 경우)을 실행한 뒤 git push 명령어를 날리면 된다. 'git status'에서 내가 지금 고친 파일만 눈에 뜨인다고 안심하고 있을 일이 아니다.



댓글 없음: