2026년 7월 28일 화요일

드럼 패턴 데이터의 추상화와 정규화


드럼 연주 기능을 고리로 하여 과거(Nano Ardule, 과거라고 해 봐야 너무나 가까운 반년 전이지만)와 현재(Fluid Ardule)의 통섭이 일어나고 있다고 아주 좋아하고 있었다. 그 즐거움은 며칠 가지 않았다. 과거의 작업 결과물이 완벽하지 않았음을 깨닫는 계기가 되고 말았으니까. 고쳐야 할 곳이 꽤 많아져서 약간은 망연자실한 상태이다.

Nano Ardule 개발 시절에 내가 확립해 둔 드럼 패턴 체계는 오직 4박자를 위한 것이었다. 4박자만큼은 아니더라도 널리 쓰이는 3박자(예: 왈츠), 그리고 5박자나 7박자 같은 비정형 박자를 다루려면 드럼 패턴 체계 자체를 근본적으로 뜯어고쳐야 한다고 생각하고 있었다. 그런데 막상 Fluid Ardule에 드럼 재생 기능을 넣으면서 살펴보니 과거에 만든 체계가 꽤 견고하고 합리적이라서 3박자나 비정형 박자를 처리하는데 별다른 문제가 없었다. 

게다가 더욱 까다롭게 생각했던 flam 처리도 sidecar 파일 방식으로 어렵지 않게 구현할 수 있었다. 이러한 결과에 만족하면서 flam이 포함된 왈츠 패턴 하나를 재생하고 있는데 tom 소리가 빠져 있는 것이 아닌가? 분명히 이미지로 만든 패턴 정보에는 low 계열의 tom을 3박째에서 2회(8분음표) 두드리고 있는데 처리가 끝난 ADT/ADP에서는 소리가 들리지 않는다.

원본 MIDI 파일에는 분명히 노트가 남아 있었다. 원인을 찾아 보았다. Tom 계열의 노트를 처리하면서 누락이 된 것이었다! 현재 사용하는 12개 slot 정보는 다음과 같다.

SLOT0=KK@36,KICK
SLOT1=SN@38,SNARE
SLOT2=CH@42,HH_CL
SLOT3=OH@46,HH_OP
SLOT4=LT@45,TOM_L
SLOT5=MT@47,TOM_M
SLOT6=HT@50,TOM_H
SLOT7=RD@51,RIDE
SLOT8=CR@49,CRASH
SLOT9=RM@37,RIM
SLOT10=CL@39,CLAP
SLOT11=PH@44,HH_PED

Tom은 High-Middle-Low로 그럴싸하게 배열해 놓았지만, 노트 번호를 미련하게 할당한 것이다. 원본 MIDI 파일에서는 노트 번호 43번으로 low tom(실은 high floor tom)이라고 기록되어 있었는데, 내가 쓰는 슬롯 정보에서는 이 번호가 슬그머니 사라진 것이었다. 

Rack tom의 가장 낮은 것이라 해도 floor tom의 high보다는 높은 소리를 내는데, 타악기 명의 앞부분만 보고서 애초에 tom 할당 체계를 잘못 잡은 것이다. Nano Ardule 개발 당시에 만든 스크립트(adc-mid2report.py)를 고쳐서 모든 노트에 대한 분석을 해 보라고 하였다. 이 분석 작업에는 35개의 MIDI 드럼 패턴 파일이 투입되었다.

> python .\260728a_adc-mid2report.py ..\patterns\original-midi-files\
============================================================
Directory: ..\patterns\original-midi-files
MIDI files found: 35   processed: 35   errors: 0
============================================================

Note-On Frequencies (all channels, no grouping):
  total note_on events: 13625
  ch  note  count
  10    36      3244
  10    37       294
  10    38      3009
  10    39        84
  10    42      4160
  10    43       504
  10    44       408
  10    47       652
  10    50       266
  10    51       756
  10    56       248

GM Drum Note Frequencies (channel 10, no grouping):
  note  GM instrument                 count     percent
    36  Bass Drum 1                       3244    23.809%
    37  Side Stick                         294     2.158%
    38  Acoustic Snare                    3009    22.084%
    39  Hand Clap                           84     0.617%
    42  Closed Hi-Hat                     4160    30.532%
    43  High Floor Tom                     504     3.699%
    44  Pedal Hi-Hat                       408     2.994%
    47  Low-Mid Tom                        652     4.785%
    50  High Tom                           266     1.952%
    51  Ride Cymbal 1                      756     5.549%
    56  Cowbell                            248     1.820%
  total: 13625

실제 데이터에서는 43(High Floor Tom)-47(Low-Mid Tom)-50(High Tom)을 tom 계열의 노트로 사용하고 있다. 그런데 내가 만든 slot 체계에서는 45(Low Tom)-47-50이었다. 널리 쓰이는 43번이 아예 사라지도록 잘못 설계한 것이다. 근거가 되었던 계산적 드럼 패턴학('computational drum patternology' - 아마도 내가 처음 쓰기 시작한 말)에서 잘못된 분석을 하는 바람에 tom의 대표음을 엉뚱하게 배치하는 결과를 초래하였다. 추상화(abstraction)정규화(normalization)를 제대로 하지 않는 값을 치르고 있는 셈이다.

올바른 계산적 드럼 패턴학을 위해서는 추상화를 통해 실제 악기의 사용 현황을 조사해야 한다. 그 다음에는 성격이 비슷한 악기를 그룹화한 다음, 정규화를 통해서 각 그룹에 대해 가장 대표성이 높은 악기를 대표 노트로 선택한다. 그런데 오늘의 분석 작업에서는 총 11개의 노트가 쓰였다. 즉, 12개라는 slot 제한을 초과하지 않았다. 따라서 악기를 그룹으로 묶거나 대표 노트를 고를 일도 없었던 것이다. 

물론 앞으로 더 많은 데이터를 분석해 봐야 하겠지만, 오늘의 작업만으로도 실제 데이터가 어떤 경향이 있는지를 충분히 파악할 수 있었다.

과거의 잘못을 들추어냄에 따라서 해야 할 일도 많아졌다. Nano Ardule의 온갖 유틸리티 스크립트를 고쳐야 하고, ADT 안에 하드코딩되어 있던 슬롯 정보도 바꾸어야 하며, 패턴 이미지 파일도 개정하여  GitHub에 올려야 한다. 하지만 오늘이라도 알게 된 것이 어디인가? 

음악과 관련한 취미 코딩을 하면서 추상화와 정규화를 실천하게 된 것을 다행으로 여겨야 하겠다. 음악, 납땜, 코딩, 데이터 분석... 겉으로 보기에 별로 관계가 없어 보이는 일들이 한데 어우려져서 뭔가 산출물을 만들어 내고 이와 더불어 조금씩 나아지고 있는 듯하다.

2026년 7월 26일 일요일

비정형 박자는 이미 가능했다 — ADT 설계의 재발견과 Nano Ardule·Fluid Ardule의 통섭

오늘부터 Fluid Ardule에서 사용할 드럼 패턴의 비정형 박자를 시험하기 위해 작은 명령행 파이썬 프로그램인 ADX Player를 만들고 있다. 3/4, 5/4, 7/8, 6/8처럼 4/4가 아닌 박자를 실제로 재생해 보려는 것이 이번 작업의 출발점이었다. 시험을 위한 플랫폼은 라즈베리 파이(Fluid Ardule) 그 자체이다. 다시 말해서 Fluid Ardule는 개발 대상이면서 동시에 테스트베드(testbed) 역할도 수행한다.

처음에는 비정형 박자를 지원하려면 ADT 규격과 재생기를 상당히 고쳐야 할 것으로 생각했다. 그러나 기존의 ADT v2.2b 규격을 다시 살펴보고 실제 플레이어를 구현해 보니 뜻밖의 사실이 드러났다.

ADT는 이미 비정형 박자를 표현하고 재생하는 데 필요한 구조를 갖추고 있었다. 여기에서 잠시 ADT를 고안한 이유를 설명하고 넘어가려고 한다. 

Nano Ardule를 개발하던 당시, Arduino Nano에서 SD 카드에 저장된 Standard MIDI File을 별도의 MIDI 재생 라이브러리 없이 직접 스트리밍 방식으로 재생하는 기능을 구현하였다. 메모리가 극히 제한된 환경에서 MIDI 이벤트를 실시간으로 해석하며 재생하는 것은 쉽지 않은 작업이었지만, 결국 원하는 수준의 재생기를 완성할 수 있었다.

그러나 곧 다른 문제가 드러났다. 드럼 반주만을 반복 재생하는 용도로는 MIDI가 지나치게 범용적인 포맷이었다. 특히 Arduino Nano와 같은 제한된 환경에서는 짧은 드럼 패턴을 끊김 없이 반복(loop) 재생하도록 구현하는 일이 생각보다 까다로웠다. 또한 MIDI 이벤트를 텍스트로 살펴보아서는 실제 어떤 리듬인지 직관적으로 이해하기 어려웠고, 패턴을 수정하려면 사실상 DAW와 같은 별도의 MIDI 편집기가 필요했다.

ADT는 MIDI를 대체하기 위해 만든 것이 아니다. 사람이 읽고 편집하기 쉬우면서도, 드럼 패턴을 플랫폼 독립적으로 교환하고 재생하기 위한 경량 텍스트 규격이 필요하다는 판단에서 출발하였다. ADT는 이러한 요구를 충족하는 사람이 읽을 수 있는 소스 형식이며, 이를 빠르게 저장하고 재생하기 위해 컴파일한 바이너리 캐시 형식이 ADP이다.

반복하자면 ADT와 ADP는 원래 자원이 제한된 Arduino Nano 기반의 Nano Ardule을 위해 만들어졌다. 지금 개발을 이어나가는 Fluid Ardule은 Raspberry Pi와 FluidSynth를 기반으로 훨씬 풍부한 음원과 사용자 인터페이스를 제공하는 DIY MIDI sound module이다.

두 시스템은 서로 다른 시대와 하드웨어 환경에서 만들어졌지만, 이번 비정형 박자 구현 작업을 통해 Nano Ardule에서 탄생한 ADT/ADP의 설계가 Fluid Ardule의 새로운 드럼 반주 기능으로 자연스럽게 이어지고 있다.

단순히 예전 파일 형식을 다시 사용하는 정도가 아니다. Nano Ardule에서 축적된 간결한 패턴 표현 방식과 Fluid Ardule의 소프트웨어 음원, MIDI 처리 능력, 확장 가능한 사용자 환경이 하나의 체계 안에서 결합되고 있다.

이제야 Nano Ardule과 Fluid Ardule 사이의 진정한 통섭이 이루어지고 있다고 해도 좋을 것이다.

이번에 한 일은 새로운 포맷을 발명한 것이 아니라, 이미 만들어진 규격 안에 들어 있던 일반성을 다시 확인하고 구현한 것에 가깝다. Nano Ardule 시절의 설계가 사라지지 않고, 더 강력한 Fluid Ardule 안에서 새로운 역할을 얻은 것이다.

오늘의 글에서는 복습을 겸하여 중요한 개념을 국문으로 정리하였다. 초안 작성에는 ChatGPT의 도움을 받았다. 인터넷에서 이런 종류의 글은 아마 거의 찾아볼 수 없을 것이다. 이 글은 GitHub의 README도 아니고, 소프트웨어 개발 일지도 아니며, 실용음악 이론도 아니고, 논문도 아니다. '설계 회고(Design Retrospective)'에 해당한다고 보는 것이 옳다.


드럼 패턴은 시간과 악기로 이루어진 매트릭스다

ADT의 기본 개념은 드럼 패턴을 하나의 2차원 매트릭스, 즉 행렬로 표현하는 것이다.

시간을 X축으로 놓으면 각 열(column)은 하나의 Step이 된다. 세로축의 각 행(row)은 하나의 드럼 악기, 즉 Slot이 된다. Step size를 16분음표로 정의할 경우, 아래의 매트릭스는 매우 전형적인 4비트 록 드럼 패턴을 나타낸다.

                         시간: Step →
          
Step        0 1 2 3 | 4 5 6 7 | 8 9 A B | C D E F
----------------------------------------------------
Crash       O . . . | . . . . | . . . . | . . . .
Open HH     . . . . | . . . . | . . . . | . . O .
Closed HH   . . x . | x . O . | O . x . | x . . .
Snare       . . . . | X . . . | . . . . | X . . .
Kick        O . . . | . . O . | O . . . | . O . .

예를 들어 Step 4의 Kick과 Snare 위치에 모두 타격 기호가 있다면, 재생기는 그 순간 킥과 스네어를 동시에 연주한다. 따라서 하나의 Step에는 여러 Slot의 이벤트가 함께 들어갈 수 있다.

ADT의 패턴 본문은 결국 다음과 같은 논리적 구조를 기록한다.

Pattern[step][slot] = accent level

각 셀에는 단순한 ON/OFF뿐 아니라 네 단계의 상대적 액센트가 저장된다. MIDI의 벨로시티(0-127)를 단순화한 것이다.

기호 레벨 의미
. 0 쉼, 타격 없음
- 1 약한 타격
x 2 보통 타격
o 3 강한 타격

ADT는 같은 매트릭스를 두 방향으로 기록할 수 있다

논리적으로는 시간축(X축)에 Step을 배치하고, Slot을 행으로 나열한 형태가 드럼 패턴을 눈으로 읽고 편집하기에 가장 자연스럽다.

ADT에서는 이 매트릭스를 파일에 기록할 때 각 행(row)이 무엇을 나타내느냐에 따라 두 가지 방향을 사용할 수 있다. 두 가지 기록 방식은 완전히 동일하다. 사람이 보기에는 첫 번째 방법(SLOT 방향)이 편하고, 저장 기본값은 두 번째 방법인 STEP이다.

1. SLOT 방향

ORIENTATION=SLOT에서는 한 행이 하나의 악기를 나타낸다. 따라서 본문의 행 수는 Slot 수와 같고, 각 행에는 시간 순서대로 LENGTH개의 기호가 들어간다. 

ORIENTATION=SLOT

O...O...O...O...
....X.......X...
x.x.x.x.x.x.x.x.
................
...

이 형태에서는 시간축이 가로로 진행한다.

  • 한 행 = 하나의 Slot
  • 한 열 = 하나의 Step
  • 본문 행 수 = SLOTS
  • 각 행의 문자 수 = LENGTH

드럼 머신의 스텝 시퀀서 화면과 비슷하므로 사람이 패턴을 살펴보고 편집하기에 편리하다. 위에서 사례로 든 4비트 록 드럼 패턴이 바로 이렇게 표시한 것이다. 

2. STEP 방향(default)

ORIENTATION=STEP에서는 같은 매트릭스를 90도 돌린 것처럼 기록한다. 한 행이 하나의 시간 Step이 되고, 그 행 안의 각 문자가 Slot을 나타낸다.

ORIENTATION=STEP

O.x.........
............
..x.........
............
OXx.........
...

이 형태에서는 시간이 위에서 아래로 진행한다.

  • 한 행 = 하나의 Step
  • 한 열 = 하나의 Slot
  • 본문 행 수 = LENGTH
  • 각 행의 문자 수 = SLOTS

두 표현은 서로 다른 패턴이 아니다. 하나의 동일한 Step × Slot 매트릭스를 서로 90도 회전시켜 기록한 것뿐이다.

파서는 어느 방향으로 기록된 ADT를 읽더라도 내부에서는 보통 다음과 같은 STEP 기준 구조로 정규화할 수 있다.

grid[LENGTH][SLOTS]

최근 테스트 파일에서 발생한 오류도 이 두 방향의 차이에서 비롯되었다. 본문은 SLOT 방향으로 작성했지만 ORIENTATION=SLOT을 명시하지 않아, 파서가 기본값인 STEP 방향으로 해석했던 것이다.


Step: 시간축의 최소 칸

Step은 ADT 시간축의 최소 단위이다.

Step 자체가 언제나 16분음표를 뜻하는 것은 아니다. Step 하나의 실제 시간 길이는 GRID가 정한다.

예를 들어 다음과 같이 정의되어 있다면, Step 하나는 16분음표 하나에 해당한다.

GRID=16

Step 0, Step 1, Step 2는 각각 연속된 16분음표 시간 칸이다.

플레이어는 각 Step에 들어 있는 모든 Slot을 조사하여 필요한 MIDI 드럼 노트를 동시에 출력한 뒤, GRID가 정한 시간만큼 기다리고 다음 Step으로 이동한다.


Slot: 동시에 연주할 수 있는 악기 레인

Slot은 드럼 패턴의 악기축이다.

ADT의 기본 드럼 구성에서는 12개의 Slot을 사용하며, 각 Slot은 MIDI 드럼 노트 하나와 연결된다.

SLOTS=12

SLOT0=KK@36,KICK
SLOT1=SN@38,SNARE
SLOT2=CH@42,HH_CLOSED
SLOT3=OH@46,HH_OPEN
...

KK@36은 이 Slot의 약어가 KK이고 MIDI 노트 번호가 36이라는 뜻이다.

Slot은 시간의 길이를 결정하지 않는다. 단지 각 Step에서 어떤 악기가 울리는지를 결정한다.


GRID: 시간축의 해상도

GRID는 4분음표를 기준으로 Step이 얼마나 촘촘하게 나뉘는지를 정의한다.

GRID Step 하나의 의미 4분음표당 Step 수
16 일반 16분음표 4
8T 8분음표 셋잇단음표 3
16T 16분음표 셋잇단음표 6

따라서 GRID는 패턴의 박자를 정하는 값이라기보다, 시간축을 어느 정도의 해상도로 나눌 것인지를 정하는 값이다.


8T와 16T: 셋잇단음표 그리드

GRID 이름 뒤의 T는 Triplet, 즉 셋잇단음표를 뜻한다.

GRID=8T

4분음표 하나를 3개의 동일한 Step으로 나눈다.

4분음표 1개 = 3 Step

4/4 한 마디에는 4분음표가 4개 있으므로 12 Step, 두 마디에는 24 Step이 필요하다.

TIME_SIG=4/4
GRID=8T
LENGTH=24

GRID=16T

4분음표 하나를 6개의 동일한 Step으로 나눈다.

4분음표 1개 = 6 Step

따라서 4/4 두 마디는 48 Step이 된다.

TIME_SIG=4/4
GRID=16T
LENGTH=48

이 구조 덕분에 셔플이나 트리플렛 계열의 리듬도 별도의 예외적인 재생 알고리즘 없이 표현할 수 있다.


LENGTH: 패턴 전체의 Step 수

LENGTH는 패턴에 들어 있는 전체 Step의 수이다.

ADT 패턴은 관례적으로 두 마디 길이이지만, 두 마디가 언제나 32 Step인 것은 아니다. 실제 Step 수는 박자와 GRID에 따라 달라진다.

플레이어는 Step 0부터 LENGTH - 1까지 재생한 뒤 다시 Step 0으로 돌아간다.

for step in range(LENGTH):
    play_all_slots(step)
    wait_for_grid_interval()

repeat

따라서 실제 재생 엔진에서 가장 권위 있는 패턴 길이 값은 LENGTH이다. 나의 설계에서는 패턴 길이는 의도적으로 2 bar를 가정하고 있다. Player는 두 마디 중 어느 하나만 선택하여 재생할 수 있다.


TIME_SIG: 패턴의 박자

TIME_SIG는 Time Signature, 즉 패턴의 박자를 나타낸다.

TIME_SIG=4/4
TIME_SIG=3/4
TIME_SIG=5/4
TIME_SIG=7/8
TIME_SIG=6/8

분자는 한 마디에 들어 있는 기준 음표의 수를 나타내고, 분모는 그 기준 음표의 종류를 나타낸다.

예를 들어 7/8은 한 마디가 8분음표 일곱 개 길이라는 뜻이다.

TIME_SIG는 음악적 의미, 문서화, 마디 구분, 에디터 표시 및 LENGTH 검증에 사용된다.

그러나 현재의 ADT 재생 구조에서는 매 Step의 실제 간격은 GRID가 정하고, 루프의 끝은 LENGTH가 정한다. 따라서 플레이어는 TIME_SIG를 직접 참조하지 않고도 패턴을 정확한 길이로 재생할 수 있다.

이것은 TIME_SIG가 중요하지 않다는 뜻이 아니다. TIME_SIG는 패턴의 음악적 구조를 설명하고, GRID 및 LENGTH가 서로 일치하는지를 확인하는 중요한 메타데이터이다.


박자와 GRID에 따른 LENGTH 계산

분모가 4인 박자만 생각한다면 다음과 같이 간단하게 계산할 수 있다.

LENGTH
= 마디 수 × 한 마디의 박 수 × 한 박당 Step 수

그러나 7/8이나 6/8처럼 분모가 4가 아닌 박자까지 일반화하려면 박자의 분모도 계산에 반영해야 한다.

LENGTH
= 마디 수
× TIME_SIG 분자
× (4 / TIME_SIG 분모)
× GRID의 4분음표당 Step 수

ADT의 표준 패턴 길이인 두 마디를 기준으로 몇 가지 예를 계산하면 다음과 같다.

박자 GRID 한 마디 Step 두 마디 LENGTH
4/4 16 16 32
3/4 16 12 24
5/4 16 20 40
7/8 16 14 28
3/4 8T 9 18
6/8 8T 9 18

여기에서 3/4와 6/8은 마디의 전체 시간 길이는 같을 수 있지만, 음악적인 강세 구조는 다르다. 이 차이는 TIME_SIG가 설명하고, 실제 시간축의 세분화는 GRID가 담당한다.


왜 v2.2b만으로 비정형 박자가 가능한가

5/4를 예로 들어 보자.

GRID=16에서는 4분음표 한 박이 4 Step이다. 5/4 한 마디는 20 Step이고, ADT의 기본 길이인 두 마디는 40 Step이다.

TIME_SIG=5/4
GRID=16
LENGTH=40

플레이어는 40개의 Step을 재생하고 루프하면 된다. 5/4 전용 재생 루틴은 필요하지 않다.

7/8도 마찬가지다. GRID=16에서는 8분음표 하나가 2 Step이므로 한 마디는 14 Step, 두 마디는 28 Step이다.

TIME_SIG=7/8
GRID=16
LENGTH=28

재생기는 28 Step을 순서대로 재생한 뒤 처음으로 돌아가면 된다.

결국 비정형 박자를 가능하게 하는 핵심은 특정 박자별 예외 처리 코드가 아니라 다음 세 요소의 분리이다.

  • TIME_SIG: 음악적인 박자
  • GRID: 시간축의 해상도
  • LENGTH: 패턴 전체의 Step 수

이번 정리 작업의 의미

이번 문서 정리와 ADX Player 제작은 ADT에 새로운 기능을 억지로 추가하기 위한 작업이 아니다.

목적은 3/4, 5/4, 7/8, 6/8과 같은 비정형 박자를 실제로 구현하고 검증하는 것이다.

그 과정에서 확인한 것은 기존 ADT v2.2b 규격의 완성도가 예상보다 높았다는 사실이다.

ADT는 이미 다음 요소를 서로 독립적으로 정의하고 있었다.

  • 박자를 나타내는 TIME_SIG
  • 시간 해상도를 나타내는 GRID
  • 전체 재생 길이를 나타내는 LENGTH
  • 악기축을 나타내는 SLOT
  • STEP 방향과 SLOT 방향의 두 가지 본문 표현
  • 직선 계열과 트리플렛 계열의 GRID

특히 재생 엔진이 TIME_SIG에 종속되지 않고 LENGTH를 권위 있는 루프 길이로 사용하는 구조 덕분에, 기존의 동일한 재생 루프로 다양한 박자를 처리할 수 있었다.

과거에는 주로 4/4 패턴만 제작하고 사용했기 때문에 이 일반성이 눈에 잘 띄지 않았을 뿐이다.

비정형 박자는 새로 가능해진 것이 아니다. 이미 가능했으며, 이번 작업을 통해 그 사실을 명시적으로 확인한 것이다.

다만 7/8이나 6/8처럼 분모가 4가 아닌 박자까지 문서에서 완전히 일반화하려면 LENGTH 계산식에 TIME_SIG의 분모를 분명하게 반영할 필요가 있다. 이것은 파일 구조나 재생 방식의 변경이 아니라, 이미 가능한 동작을 더 정확하게 설명하기 위한 문서상의 보완이다.

ADT의 핵심 철학은 다음과 같이 요약할 수 있다.

ADT는 드럼 패턴을 Step과 Slot으로 이루어진 매트릭스로 표현한다. GRID는 각 Step의 시간 간격을 정하고, LENGTH는 패턴의 전체 길이를 정하며, TIME_SIG는 그 시간 구조의 음악적 박자를 설명한다.

SLOT 방향에서는 시간이 가로로 흐르고 악기가 세로로 배열된다. STEP 방향에서는 같은 매트릭스를 90도 돌려 시간이 세로로 흐르고 악기가 가로로 배열된다.

이 단순하고 분리된 구조 덕분에 ADT는 4/4에 갇혀 있지 않다. 3/4, 5/4, 7/8, 6/8과 트리플렛 계열 패턴도 동일한 자료 구조와 동일한 재생 엔진으로 처리할 수 있다.

이번 작업은 ADT를 새로 설계하는 작업이 아니라, 이미 잘 만들어져 있던 설계의 잠재력을 발견하고 실제로 증명하는 작업이다.

ADT는 오래된 포맷이 아니다. ADP의 장점을 계승하면서 사람 친화적인 텍스트 규격으로 새롭게 설계되었다. 그리고 불과 1년 만에 ADX Player를 통해 4/4를 넘어 다양한 박자를 자연스럽게 수용할 수 있음을 확인했다. 결과적으로 Nano Ardule에서 시작된 ADP와 Fluid Ardule에서 발전한 ADT는 이제 하나의 패턴 생태계를 이루게 되었고, 이것이야말로 두 프로젝트의 진정한 통섭이라 할 수 있다.


(회고) 왜 ADT v2.3 Final Draft를 만들었었나?

ADT v2.2b는 이미 충분히 완성도가 높은 규격이었다. 실제로 이번 작업을 진행하면서 가장 놀라웠던 점은 새로운 기능을 추가하지 않고도 3/4, 5/4, 6/8, 7/8과 같은 다양한 박자를 자연스럽게 표현할 수 있었다는 사실이다.

그렇다면 굳이 ADT v2.3 Final Draft를 만들 필요가 있었던 이유는 무엇일까?

결론부터 말하면, 규격을 바꾸기 위해서가 아니라 규격이 원래 지니고 있던 일반성을 더욱 정확하게 문서화하기 위해서였다.

이번에 ADX Player를 구현하면서 4/4가 아닌 여러 박자를 실제로 재생해 보았다. 그 과정에서 ADT의 핵심 요소인 TIME_SIG, GRID, LENGTH가 특정 박자에 종속되지 않는 일반적인 구조임을 다시 확인할 수 있었다.

v2.2b에도 이러한 개념은 이미 포함되어 있었다. 다만 설명과 예제가 주로 4/4 박자를 중심으로 작성되어 있었기 때문에, 독자가 ADT를 4/4 전용 규격으로 오해할 여지가 있었다. 또한 LENGTH를 계산하는 설명도 분모가 4가 아닌 박자까지 포괄하도록 더욱 일반화할 필요가 있었다.

따라서 v2.3 Final Draft에서는 다음 사항을 명확히 하거나 보완하였다.

  • ADT가 4/4뿐 아니라 다양한 박자를 표현할 수 있는 일반적인 패턴 규격임을 명시하였다.
  • TIME_SIG, GRID, LENGTH 사이의 관계를 더욱 정확하게 설명하였다.
  • 박자표의 분모까지 반영할 수 있도록 LENGTH 계산 원리를 일반화하였다.
  • 8T16T 등 트리플렛 그리드의 의미를 보완하였다.
  • STEPSLOT 표현이 서로 90도 회전한 관계임을 분명히 하였다.
  • 3/4, 5/4, 6/8, 7/8 등의 예제를 추가하여 규격의 일반성을 실제로 확인할 수 있게 하였다.

즉, v2.3은 새로운 기능을 추가하거나 파일 구조를 바꾼 버전이라기보다, v2.2b에 이미 들어 있던 설계 의도를 구현 결과에 맞추어 더 정확하게 설명하고 문서의 완성도를 높인 버전이라고 할 수 있다.

Final Draft라는 표현도 이러한 성격을 나타낸다. 규격의 핵심 구조는 사실상 확정되었지만, ADX Player와 실제 패턴을 통해 마지막 검증을 거친 뒤 정식 v2.3으로 확정하기 위한 최종 검토본이라는 뜻이다.

특히 이번 작업에서는 Nano Ardule에서 출발한 ADP의 간결한 패턴 구조와, 이후 사람이 읽고 편집할 수 있도록 설계한 ADT가 Raspberry Pi 기반의 Fluid Ardule에서 다시 활용될 수 있음이 확인되었다. 과거의 설계를 단순히 보존하는 데 그치지 않고, 새로운 재생 환경에서 그 일반성과 확장성을 실제로 증명한 것이다.

그런 의미에서 v2.3 Final Draft는 단순한 문서 개정판이 아니다. Nano Ardule과 Fluid Ardule의 진정한 통섭이 이루어지고 있음을 보여 주는 하나의 이정표이기도 하다.

ADT v2.3은 현재의 설계 목표를 대부분 달성하였다. 앞으로는 기존 구조를 유지하면서 표현력을 조금씩 확장해 나갈 예정이다. 현재 검토 중인 기능으로는 Legacy UI의 12슬롯에 제한되지 않는 사용자 정의 드럼 배열(Custom Drum Set) 과, 드럼 연주의 표현력을 높이기 위한 Flam 지원 등이 있다.

반면 Swing이나 Humanize와 같은 기능은 패턴 데이터 자체의 속성이라기보다 재생 엔진의 동작에 가까우므로, 포맷에 포함하기보다는 플레이어의 선택적 재생 옵션으로 다루는 방안을 우선 고려하고 있다.

2026년 7월 25일 토요일

Fluid Ardule에 드럼 패턴 재생 기능을 넣다

Fluid Ardule은 '전원을 넣고 키보드를 연결하면 즉시 연주 가능'한 MIDI 사운드 모듈을 지향한다. 인터넷 라디오, 각종 오디오 음원 파일 재생, 블루투스 오디오 재생 기능은 재미와 활용성을 높이기 위하여 추가한 것이다. 라즈베리파이 3B라는 제한된 하드웨어를 바탕으로 하기 때문에 샘플러라든가 작은 DAW와 같은 기능을 넣으려는 욕심을 철저히 차단하고 있다. 그래서 JACK이나 PortAudio 등을 절대 쓰지 않으며, 오로지 ALSA만을 이용한 단순하고 빠른 처리를 목표로 하였다.

하지만 드럼 재생 기능만큼은 넣어 보고 싶었다. Nano Ardule을 개발하면서 값진 자산으로 남은 드럼 패턴 라이브러리를 이용하면 어렵지 않게 Fluid Ardule의 운영 스크립트에서 드럼 패턴을 반복 재생하고, 연결된 키보드를 이용하여 드럼과 동시 연주도 가능할 것 같았다.



Nano Ardule 개발 당시 공개된 드럼 MID 파일을 분석하여 2-bar 단위의 패턴을 장르별로 정리해 둔 일이 있다. 이를 위한 두 가지의 전용 파일 포맷도 개발해 두었다. ADT는 사람이 읽고 편집할 수 있는 파일이고, 이를 검증하여 작은 바이너리 캐시로 만든 것은 ADP이다. ADP는 아두이노 나노(에브리)의 작은 메모리에도 비상용으로 수십개 정도는 넣을 수 있다.

사실 아두이노 나노보다 성능이 훨씬 좋은 라즈베리 파이에서는 ADT를 그대로 재생할 수 있다. 하지만 이를 위해서는 운영 스크립트 안에 텍스트 파서가 들어가야 하고, 잘못 작성된 패턴을 검사하는 코드도 필요하다. 예외 처리도 늘어났을 것이고, 앞으로 ADT 문법이 바뀔 때마다 Fluid Ardule도 함께 수정해야 했을지 모른다. 

하지만 ADP는 대단히 단순하다. 이미 검증이 다 끝난 상태이기 때문이다. 텍스트 파일을 다룰 때 필요한 파서 같은 것을 요구하지 않는다.

  • ADP 파일을 연다.
  • 헤더를 확인한다.
  • 스텝 데이터를 읽는다.
  • 해당 스텝의 드럼 음을 출력한다.

이것으로 끝이다. "Play with Drums"라는 메뉴를 넣을 위치를 결정하고, 대략의 화면을 구상한 뒤 지시문을 만들어서 ChatGPT에 ADP 파일 사양 문서와 함께 밀어 넣었다. 그것으로 끝. 인코더를 돌려서 BPM을 조절하고, 키보드 입력 신호를 동시에 연주하는 기능도 순식간에 구현하였다. 오히려 화면 안에서 텍스트 배치를 보기 좋게 조절하는 것에 가장 많은 시간을 쏟았다.

Nano Ardule 개발 당시 꽤 신경을 써서 만든 '드럼 패턴 데이터 표준안'이 결국 미래의 나를 위한 좋은 선물이었던 것이다. 물론 앞으로도 ADT는 필요하다. 사람이 읽고 수정할 수 있는 원본이 있어야 하기 때문이다. 그러나 실제 연주를 담당하는 프로그램에게는 검증이 끝난 ADP가 더 적합하다. 만약 2-bar MIDI drum pattern을 재생 대상으로 삼았더라면 타이밍 계산과 MIDI 이벤트 해석, 스케줄링을 처리하느라 개발 과정은 그야말로 재앙이 되었을 것이다. MIDI drum pattern은 악기 사용 빈도를 계산하고 ADT → ADP를 만드는 과정에서 매우 유용한 raw data 역할을 한 것은 솔직하게 시인한다.

내가 만든 체계에서는 드럼킷을 구성하는 악기(slot)를 12개로 제한한다. 실용적으로는 큰 문제가 없다. ADP에서는 슬롯 번호마다 다음과 같이 정해진 악기가 할당된다. 반면 ADT는 12개 슬롯이라는 원칙을 지키기만 한다면 다른 악기를 넣을 수 있다. 예를 들어 카우벨이나 탬버린 같은 것. 따라서 새로운 패턴을 만들 때에는 ADT가 필요하다.

노트 넘버 37번은 rim shot이 아니라 side stick이 맞을 것이다.

이러한 타악기 배치는 임의로 정한 것이 아니다. 인터넷에 공개된 다수의 드럼 패턴 파일(.MID)을 분석한 결과물이므로 일종의 (빅)데이터 분석을 통하여 얻은 결론이다. 이를 컴퓨터 키보드(16키) 또는 AKAI MPK MINI의 패드(8키 x 2뱅크)에 할당하여 입력하기 위해 나름대로 머리를 싸매서 고민을 한 결과가 바로 다음의 스펙 문서이다. 

APS Drum Instrument Sets & Pad Mapping - Reference Specification

실은 요즘 며칠 작업을 하면서 이 문서가 조금 잘못된 것을 깨달았고, 조금씩 수정을 가하고 있다. 결론적으로는 Legacy UI 12 Set를 실질적인 표준으로 삼는 것이 더욱 바람직하다. 내가 만들어 놓은 450개 가까운 ADT/ADP는 실제로 Legacy UI 12 Set를 따르고 있었다. 처음부터 목표를 세워서 이를 구현하기 위해 표준을 설계한 것이 아니라, 공개된 데이터를 분석하고 실제로 사용 가능한 형태로 다듬는 과정에서 자연스럽게 하나의 표준이 만들어졌던 것이다. 어쩌면 내가 숱하게 남긴 기록에도 불구하고 개발 과정을 정확하게 기억하지 못했을 수도 있지만.

결국 좋은 데이터 포맷이란 단순히 파일 크기가 작거나 처리 속도가 빠른 것이 아니다. 사람이 이해하고 수정할 수 있는 원본과, 기계가 빠르고 안정적으로 처리할 수 있는 표현을 적절히 분리하는 것이다. ADT와 ADP는 바로 그런 역할 분담을 목표로 만들어졌다. 몇 달이 지난 지금도 거의 수정 없이 새로운 프로젝트에서 다시 활용할 수 있었다는 사실이, 당시의 설계가 나쁘지 않았음을 증명해 주는 것 같다. 미래의 나는, 과거의 내가 남겨 둔 작은 선물을 기분 좋게 다시 꺼내 쓸 수 있었다.

오키나와에서 왼쪽 차선으로 운전해 보기

아들이 기획한 오키나와 가족 여행으로 2026년 이른 여름 휴가를 대신하였다. 여행을 다녀온 즉시 글을 쓰지 못하는 바람에 기억이 점점 흐려짐은 아쉬운 일이다. 아들이 아니었으면 어쩌면 평생 국제운전면허증을 발급받아서 외국에서 운전을 한다는 도전 자체를 하지 않았을지도 모른다. 올 한해 동안 아들이 기획한 효도 관광을 두 차례나 일본으로 다녀온 셈이다.

오키나와 나하 국제공항에서.


오키나와현립 박물관・미술관

아들과 번갈아 운전한 차량은 토요타 아쿠아(하이브리드).


오리온 맥주와 블루실 아이스크림, 그리고 오키나와 특유의 '포크 음악'은 이제 영원히 기억하게 될 것 같다. 일본 본토를 둘러싼 갈등과 2차대전 끝무렵에 오키나와 주민이 겪은 아픔도 어느 정도는 이해할 수 있었다. 

오키나와 추라우미 수족관



오키나와 해양 엑스포 공원 내 해양 문화관은 볼거리가 정말 많았다.


사위 덕분에 '입덕'하게 된 루트비어. 사위인 Gavin은 오키나와에서 유명한 브랜드인 A&W보다 Sprecher를 더 좋아한다. 사위의 최애 한국 과자는 오징어땅콩.

왼손으로 변속을 하고 오른손으로 방향지시등을 조작하는 것이 정말 어색했다. 깜빡이를 켠다고 생각했는데 어느새 와이퍼가 좌우로 왔다갔다! 게다가 우회전, 즉 우리 방식으로는 좌회전을 하는 방식이 왜 이렇게 생소한지! 우리의 교통규칙은 해야 할 것과 하지 말아야 할 것을 전부 엄격하게 규정하여 보여주지만, 이곳은 기본적으로 모든 우회전은 비보호에 해당하며 중앙선을 넘어서 반대편 골목으로 넘어가는 것이 전혀 교통규칙 위반이 아니다. 양보가 몸에 밴 사람들이라서 다들 경적 한 번 울리지 않고 여유있게 차량을 운행하고 있었다.


산토리니 느낌이 난다는 세나가섬의 우미카지 테라스.


나하 시내를 달리는 모노레일 유이 레일.

오키나와 평화기념공원 내 전시관에서는 사진 촬영이 금지되어 있었다. 일제 강점기를 겪은 대한민국 국민으로서 오키나와 주민들의 전쟁 피해—일본 정부에 의한, 그리고 미군에 의한—에 대해서는 복잡한 마음이 들었다.




오키나와 전통 현악기인 산신(三線). 뱀가죽으로 몸통을 둘렀다. 중국의 삼현에서 유래하였으며 일본 본토로 넘어가 샤미센이 되었다.

제주도에는 돌하르방이 있다면, 오키나와에는 수호신에 해당하는 '시사'가 있다.

저녁 무렵의 어메리카 빌리지.


바쁜 일상 중에 잠시 쉼표를 찍고 갈 수 있게 해 준 아들에게 고마움을 느낀다. 건강이 허락하는 한 가급적 많이 돌아다니련다.

2026년 7월 24일 금요일

다시 하루 걸러 하루 달리기로 운동 주기를 바꾸어 보다

2026년 7월 말이면 달리기를 시작한 지 꼭 2년이 된다. 일반적인 체력이나 의지가 있는 사람이라면 이미 하프마라톤 코스 정도는 최소한 한 번쯤 소화하였을지도 모르겠다. 그에 비하면 나의 성적은 초라하다. 아직까지 6분 이내의 평균 페이스, 쉽게 말하여 30분에 5km 이상 달리기도 달성하지 못하고 있으니 말이다.

달리기 2주년을 앞두고 받은 배지
어제 받은 배지. 집을 나설 때에는 '오늘은 몸이 좀 피곤하니 과연 1km나 달릴 수 있을까?'하고 걱정을 하지만, 결국은 쉬지 않고 5km를 달리게 된다.

처음에는 하루 뛰고 하루 쉬는 것을 목표로 하였으나 피로감 극복이 힘들어서 하루를 달리고 이틀을 쉬는 것으로 운동 주기를 바꾸어 꽤 오래 지속하였다. 한 번에 달린 거리는 6~7.5km 정도였다. 최근에는 출장과 여행, 날씨 등으로 쉬는 기간이 더 길어지는 일도 많았다.

지속 가능성을 높이기 위하여 이번 주부터는 한 번에 달리는 거리를 5km로 약간 줄이고, 다시 처음과 같이 하루 걸러 뛰는 방식으로 돌아가기로 하였다. 만약 2~3km 정도라면 매일 뛰어도 괜찮을 것이다. 주 3회가 아니라 무조건 이틀에 한 번 달리기이다.

이번 주 달리기 기록
금주에는 하루 뛰고 하루 쉬기를 3회 반복하였다.

달리기를 시작한 이후 체중은 눈에 띄게 줄었다. 그러나 나이가 들면서 근육량 감소는 지속되고 있다. 오른쪽 상완골 대결절 1분 골절을 극복하기 위한 목적으로 시작한 아령 운동 정도로는 어림도 없는 것 같다. 이번 달 초에 받은 건강검진의 인바디 검사 결과는 정말 초라하였다.

달리기를 유일한 운동으로 삼아 심폐지구력을 향상시키는 것만으로는 당연히 근육량 증가뿐만 아니라 유지도 힘든 것 아니겠는가? 피트니스 클럽을 가지 않더라도 특별한 기구 없이 집에서 할 수 있는 근육 운동 방법이 있을 것이니 검색을 해 봐야겠다.

ChatGPT가 자동 생성한 기구 없이 집에서 하는 근력운동법을 아래에 소개하였다. 과거에 쓴 글에서는 아령 운동법도 소개한 일이 있다(긴 여행 뒤 일상으로 돌아와 다시 운동하기).

50대 중반을 위한 집에서 하는 근력운동법
ChatGPT가 자동 생성한 근력운동법.

먹는 것에 대한 유혹도 견뎌내야 하고, 운동 계획은 더욱 치밀하게 세워서 끈기 있게 실천해야 한다. 건강한 몸을 유지하는 것이 참 어렵다. 나 혼자 이렇게 궁리하고 실천할 것이 아니라 아내에게도 운동의 중요성을 설파해야 하는데, 참 걱정이다.

2026년 7월 22일 수요일

천박한 표어

표어는 조직의 철학을 압축한 문장이다. 좋은 표어는 짧지만 오래 남는다. 그 조직이 왜 존재하는지, 무엇을 지향하는지를 몇 마디 말로 설명한다. 그래서 표어를 만드는 일은 쉽지만, 좋은 표어를 만드는 일은 어렵다. 여기서는 새로운 프로젝트와 사업, 서비스의 이름도 넓은 의미의 표어에 포함하기로 한다.

좋은 표어는 처음에는 다소 생소할 수 있다. 대개 신조어에 바탕을 두기 때문이다. 하지만 좋은 표어는 스스로를 설명할 수 있다(self-explanatory). 그 이름을 듣는 것만으로 자연스럽게 의미가 전달되고, 시간이 흐를수록 이 표어를 내세우는 조직의 철학과 함께 사람들의 기억 속에 자리 잡는다.

반대로 천박한 표어는 이름보다 설명이 길다. 회의마다, 발표마다, 문서마다 '이 이름은 이런 뜻입니다.'를 반복해야 한다. 정작 설명을 다 듣고도 '그래서 왜 이런 이름을 붙였지?'라는 의문이 남는다면, 그 표어는 이미 목적을 잃은 것이다. 만약 권력의 기울어진 운동장에서 이러한 의문이 제기되면, 그 표어를 이해하지 못하는 '하급자'에게 십중팔구 그 잘못이 돌아간다.

또 하나의 기준이 있다. 몇 년이 지나도 이름이 입에 잘 붙지 않는다면, 그것도 좋은 이름은 아니다. 사람들은 억지로 만든 이름을 오래 기억하지 않는다. 결국 줄여 부르거나 다른 이름으로 바꾸어 부른다. 이름은 사람이 적응해야 하는 대상이 아니라, 사람이 자연스럽게 받아들이는 것이어야 한다.

이 원칙은 법과 정책에도 그대로 적용된다. 좋은 법은 끊임없이 자신의 존재 이유를 변명하지 않는다. 만약 담당자가 수년 동안 '법이 있으니 해야 합니다.', '제도가 생겼으니 따라야 합니다.'를 반복해서 설명해야 한다면, 문제는 국민이나 연구자가 아니라 법과 제도에 있을 가능성이 크다.

법이 있으니 중요한 것이 아니라, 중요한 일이기 때문에 법이 만들어진 것이고, 또 그래야 한다. 좋은 법은 시간이 흐를수록 왜 필요한지 스스로 설명한다. 좋은 정책은 담당자가 바뀌어도 살아남는다. 정책의 생명력은 추진자의 열정보다 해결하려는 문제의 타당성에서 나온다.

표어도 결국 다르지 않다. 이름은 철학을 담는 그릇이다. 그릇이 내용을 압도하기 시작하면 사람들은 철학이 아니라 이름만 기억하게 된다. 그래서 새로운 표어를 볼 때마다 나는 먼저 묻는다.

이 이름은 스스로를 설명할 수 있는가.

좋은 표어는 설명을 요구하지 않는다. 설명을 들으면 의미가 더욱 깊어지며, 이것은 깊어질수록 좋은 일이다. 반대로 표어를 이해시키는 데 끊임없이 에너지를 써야 한다면, 그것은 철학을 담은 이름이 아니라 포장에 가깝다.

좋은 표어는 조직의 철학을 설명한다. 천박한 표어는 표어 자체를 설명하느라 조직의 철학을 설명할 시간을 빼앗는다. 표어가 철학을 대신하는 순간, 조직은 이름을 만들고 철학을 잃는다.

2026년 7월 15일 수요일

Fluid Ardule, 블루투스 오디오 기능까지 넣어도 될까?

 


수 개월 동안의 개발을 거쳐 이제 겨우 DIY synth module로서 안정적인 작동을 하게 된 Fluid Ardule에 자꾸 새로운 기능을 욱여넣는 것이 과연 올바른 일인지 고민을 하고 있다. Fluid Ardule은 리눅스 기반의 운영체계로 돌아가는 매우 작은 컴퓨터이다. 따라서 오디오를 다루는 범용 기기로서 원하기만 한다면 새로운 기능을 추가해도 충분히 감당할 수 있다. 다만 건반을 연결하여 선택한 악기 음색으로 연주한다는 기본 기능에 지장을 주어서는 곤란하다.

재미와 활용성을 모두 높이기 위해서 처음부터 추구했던 것은 음원 파일과 인터넷 라디오 재생이었다. 여기까지는 큰 문제가 없었다. 그러나 자연스럽게도 다음 단계의 욕심이 발동하였으니 그것은 바로 블루투스 오디오 기능이다. 신뢰할 수 있는 기기를 미리 등록해 놓은 뒤, 필요한 때에 UI를 조작해서 블루투스 페어링을 하여 휴대폰에서 송신하는 음악을 재생하는 것.

부팅 과정에 걸리는 시간을 최소화하기 위해 블루투스 관련 기능은 전부 막은 상태였다. SSH로 접속하여 이를 해제한 다음, 단계별로 테스트를 진행하였다. 음악이 흘러나오게 만드는 데에는 많은 시간이 걸리지는 않았다. 실험 기록은 별도의 문서 Experimental Documents - Bluetooth Audio Activation and Pairing (Raspberry Pi OS Trixie)에 기록해 두었다.

블루투스로 음원을 들으면서 건반을 연주하겠다는 욕심을 가져서는 안 된다. 그것은 Pi의 내장 마이크로SD카드나 USB 드라이브에 수록된 음원 파일을 재생할 때와도 같은 제약 조건이라고 받아들이는 것이 낫다. 물론 기술적으로는 가능하다. 하지만 그 순간부터 JACK, PulseAudio, PipeWire가 하나둘 등장하기 시작한다. 그 길은 기능이 늘어나는 길이기도 하지만, 동시에 유지보수가 급격히 어려워지는 길이기도 한다. 적어도 지금의 Fluid Ardule에서는 그 문을 열 생각은 없다. 나에게는 그곳이 '지옥으로 들어가는 입구'처럼 보이기 때문이다.

최근 Fluid Ardule UI에서 console로 진입하는 방법을 구현해 놓은 일이 있다. 블루투스 기기의 최초 등록은 SSH나 console을 통해서 진행하고, UI에서는 이미 등록된 기기를 연결하거나 해제하는 방식으로 운영하면 매우 간단할 것이다. 블루투스 오디오 재생 중에는 다른 기능으로 건너뛰는 것을 제한할 것이다. 그것은 Combi의 운영 방식과 유사하다.

아직 운영 스크립트에 이 기능을 넣을지 여부는 결정하지 않았다. 어쩌면 한동안은 Experimental 문서로만 남아 있을지도 모른다. 하지만 이번 실험을 통해 적어도 '할 수 있는 일'과 '하지 않기로 한 일'의 경계는 한층 분명해졌다. 프로젝트가 커질수록 새로운 기능을 추가하는 일보다, 그 유혹을 적절한 선에서 멈추는 일이 더 어려워진다. Fluid Ardule도 이제는 그런 고민을 해야 하는 단계에 이른 것 같다. 그 유혹에 넘어갈 때, Fluid Ardule은 컴퓨터 옆에 놓고 언제든지 즐길 수 있는 Desktop Music Workstation에 가까워지는 것은 사실이다. 이러다가 녹음 기능까지 넣고 싶어지면 절대로 안된다! 끝을 모르는 지옥의 입구로 진입하는 일은 없어야 하니까 말이다.


2026년 7월 19일 업데이트

이미 나흘 전, 그러니까 이른 여름 휴가를 떠나기 직전에 운영 스크립트에 블루투스 오디오 재생 기능을 넣었다. GitHub에도 스크립트를 올리고 관련 문서도 전부 수정하였다(commit 2e6b405, 스크립트 버전 260715f). Why not? 




2026년 7월 11일 토요일

Fluid Ardule 소개용 동영상을 새로 만들다

누구에게나 멋진 계획이 있다. 졸작을 만들어내기 전까지는...

인클로저까지 가공하여 만들고, 운영 소프트웨어의 기능과 안정성도 현저히 개선된 지금이야말로 Fluid Ardule의 본격적인 소개 영상을 만들어서 공개할 시점이다. 지저분한 물건을 가릴 배경지까지 구입하여 늘어뜨린 것은 좋았다.

나름대로 시나리오를 구성하여 촬영을 하였는데, 별로 마음에 들지 않는다. 게다가 OpenShot Video Editor는 왜 이렇게 말썽인 것인가? 최신 버전으로 업그레이드했지만 별로 나아지지 않았다. 오늘 작업에서 새로 발견한 문제점은 다음과 같다.

  1. 캡션 종료 시 1프레임 플래시

    일부 캡션이 끝나는 순간, 방금 사라진 캡션이 약 1프레임 동안 다시 나타났다 사라지는 현상이 발생했다. 이 문제는 미리보기뿐 아니라 내보낸 MP4 파일에서도 확인되었으며, 모든 캡션에서 동일하게 나타나지는 않았다.

  2. 캡션 배경 박스 크기 오류

    특정 캡션에서 반투명 배경 박스가 위쪽으로 비정상적으로 크게 확장되었다. 같은 설정을 사용한 다른 캡션은 정상적으로 표시되었고, 문제가 있는 캡션을 다시 만들자 정상으로 돌아왔다.

  3. 첫 PNG 타이틀이 내보내기에서 누락

    영상의 첫 화면에 배치한 PNG 타이틀은 미리보기에서는 정상적으로 보였지만, 최종 MP4 파일에서는 아예 나타나지 않았다.

  4. 마지막 PNG 슬라이드가 내보내기에서 누락

    영상 끝에 배치한 PNG 엔딩 슬라이드도 미리보기에서는 정상적으로 표시되었지만, 내보낸 영상에서는 빠져 있었다.

3번과 4번은 처음 접하는 문제점이었다. 유튜브에 올린 영상은 이 문제 때문에 마지막 화면이 수 초 동안 암흑 + 배경으로 처리되었다. 어쩌면 이제는 OpenShot을 졸업할 때가 된 것 같다. Kdenlive가 무료 오픈소스 비디오 편집 프로그램으로서는 더 나은 선택이라고 한다. 

OpenShot과 Kdenlive 비교

항목 OpenShot Kdenlive
사용 난이도 초보자가 배우기 쉽고 화면 구성이 단순하다. 기능이 많아 처음에는 다소 복잡하지만 익숙해지면 작업 효율이 높다.
편집 방식 간단한 자르기, 이어 붙이기, 이미지 삽입 등에 적합하다. 멀티트랙 편집, 복잡한 타임라인 구성, 중첩 시퀀스 등에 유리하다.
자막 기능 간편하지만 캡션 표시와 종료 과정에서 렌더링 오류가 나타날 수 있다. 전용 자막 기능이 있으며 자막 파일과 음성 인식 기반 자막 제작도 지원한다.
타이틀과 이미지 PNG와 SVG를 쉽게 배치할 수 있지만 미리보기와 내보내기 결과가 다르게 나타나는 사례가 있었다. 내장 타이틀 편집기가 강력하며 이미지와 그래픽 오버레이를 세밀하게 조절할 수 있다.
효과와 키프레임 기본적인 효과와 키프레임 애니메이션을 비교적 쉽게 적용할 수 있다. 효과와 키프레임 설정이 더 다양하고 정밀하다.
색보정 기본적인 밝기와 색상 조절에 적합하다. 색상 범위, 스코프와 다양한 색보정 효과를 제공한다.
오디오 편집 볼륨과 페이드 등 기본적인 조절이 중심이다. 오디오 믹서, 파형 표시, 필터와 효과 등 보다 전문적인 기능을 제공한다.
미리보기 성능 간단한 프로젝트에서는 가볍고 빠르지만 복잡해지면 반응이 느려질 수 있다. 프록시 클립과 미리보기 해상도 조절을 이용해 대형 프로젝트를 관리하기 좋다.
내보내기 신뢰성 사용하기는 쉽지만 프로젝트에 따라 미리보기와 최종 결과가 달라질 수 있다. 렌더링 설정이 세분화되어 있으며 비교적 복잡한 프로젝트에 적합하다.
지원 운영체제 Windows, macOS, Linux, ChromeOS Windows, macOS, Linux, BSD
가격과 라이선스 무료 오픈소스 소프트웨어 무료 오픈소스 소프트웨어
추천 용도 짧은 영상, 단순한 편집, 빠른 제작 자막이 많은 영상, 기능 소개, 장시간 프로젝트, 정밀한 편집

OpenShot은 배우기 쉽고 간단한 영상을 빠르게 만드는 데 장점이 있다. 반면 Kdenlive는 처음에는 다소 복잡하지만 자막, 타이틀, 오디오, 효과와 내보내기 설정을 더욱 정밀하게 관리할 수 있다. 편집 결과의 안정성과 확장성이 중요해진다면 Kdenlive가 더 적합한 선택이 될 수 있다.

그리하여 만들어진 오늘의 졸작은 다음과 같다. 분량은 5분을 약간 넘는다. 보다 시나리오를 철저히 구성했다면 마치 주저하듯이 버튼을 누르면서 낭비한 시간을 줄일 수 있었을 것이다. 


인터넷 라디오가 작동하는 모습을 그대로 촬영했더니 유튜브에 올렸을 때 저작권에 대한 경고가 떴다. 영상이 차단될 정도로 심각한 것은 아니라서 그냥 두기로 했다. 문제가 된 곡은 노르웨이의 밴드 Flunk의 Sit Down이란 곡이다. 경고 화면은 다음과 같다.


배경 음악, 아마추어 밴드의 기성곡 커버 등 유튜브에 영상을 올릴 때 이런 점을 유의해야 한다. 1분 이내면 괜찮다는 잘못된 정보가 너무 많다. 

숏 영상을 다시 만들 기력은 없다!

2026년 7월 9일 목요일

Fluid Ardule의 3.5인치 화면에서 리눅스 콘솔을 만나다

Fluid Ardule을 다른 사람도 만들어 쓸 수 있도록 배포하려면 어떻게 해야 할까? 요즘 이런 생각을 조금씩 하고 있다. GitHub에는 소스 코드와 설치 문서를 올려 두었지만, 실제로 Raspberry Pi OS부터 설치해서 시스템을 구성하려면 제법 많은 수고가 필요하다. 특히 Wi-Fi 설정은 사용자마다 다를 수밖에 없다.

현재 Fluid Ardule은 부팅 시간을 줄이기 위해 NetworkManager를 사용하지 않는다. 실제로 systemd-analyze blame으로 확인했을 때 NetworkManager 서비스가 부팅 과정에서 13초 이상을 차지한 적이 있었다. 전원을 켜고 빨리 악기를 사용하고 싶은 시스템에서 13초는 결코 짧은 시간이 아니다.

그래서 Fluid Ardule은 wpa_supplicantdhcpcd를 이용하는 비교적 단순한 네트워크 구성을 사용한다. 문제는 새로운 Wi-Fi를 등록할 때이다. 내가 사용하는 집 Wi-Fi와 휴대전화 핫스팟 정도만 미리 등록해 두면 별 문제가 없지만, 배포판을 사용하는 사람은 자신의 SSID와 비밀번호를 입력해야 한다. 내가 공개한 문서에서는 SSH로 연결한 터미널 창에서 명령어를 넣어서 설정을 입력하는 방법을 소개해 두었다. 그러나 아무래도 불편하지 않을 수 없다.

처음에는 여러 방법을 생각했다.

Fluid Ardule의 인코더를 돌려 ASCII 문자를 선택하게 할까? SSID는 스캔 목록에서 고르고 비밀번호만 입력하면 된다. 그러나 90개가 넘는 printable ASCII 문자를 인코더로 돌려 고르는 장면을 상상하니 썩 내키지 않았다.

Raspberry Pi를 잠시 무선 AP로 만들어 휴대전화에서 접속하게 하는 방법도 있다. 이른바 captive portal 방식이다. 편리하기는 하지만 AP 모드, DHCP, 간단한 웹 서버와 설정 페이지까지 필요하다. Wi-Fi 비밀번호 하나를 입력하기 위해 또 하나의 작은 시스템을 만드는 셈이다.

USB 키보드를 연결하게 할까? 이것도 나쁘지 않다. 하지만 그러려면 Fluid Ardule의 전용 UI 안에 텍스트 입력 기능을 새로 넣어야 한다.

이쯤에서 생각을 바꾸었다.

Fluid Ardule은 상용 전자악기가 아니다. Raspberry Pi에 운영체제를 설치하고 Arduino 펌웨어를 올리며 MIDI 장치를 연결하는 DIY 프로젝트이다. 그렇다면 사용자에게 Raspberry Pi OS와 SSH에 대한 기본적인 숙련을 요구하는 것이 그렇게 부당한 일일까?

최초 Wi-Fi는 Raspberry Pi Imager에서 설정하면 된다. 새로운 네트워크가 필요하면 SSH로 접속하여 설정 파일을 수정할 수 있다. 아무도 요구하지 않은 captive portal을 만들다가 또 며칠을 보내는 것보다는 이 편이 훨씬 낫다.

그래서 설치 문서와 네트워크 문서에 이 원칙을 명시했다. Fluid Ardule은 DIY Raspberry Pi synthesizer project이며, Raspberry Pi OS와 SSH에 대한 기본적인 숙련을 권장한다고 말이다.

여기서 오늘의 이야기가 끝났어야 했다.

그런데 문득 이런 생각이 들었다.

“Fluid Ardule 서비스를 잠시 끄고 3.5인치 TFT를 그냥 리눅스 모니터처럼 쓸 수는 없을까?”

현재 Fluid Ardule의 TFT는 /dev/fb1이라는 framebuffer 장치이다. 운영 스크립트는 Pillow로 화면을 렌더링하고 그 결과를 framebuffer에 직접 출력한다. Raspberry Pi의 Linux 콘솔은 기본적으로 다른 framebuffer를 사용하고 있다.

확인해 보았다.

$ cat /proc/fb
0 vc4drmfb
1 fb_ili9486

framebuffer 0은 HDMI 쪽이고 framebuffer 1은 ILI9486 SPI TFT이다.

Linux console의 framebuffer 연결 상태도 확인했다.

$ con2fbmap 1
console 1 is mapped to framebuffer 0

그렇다면 console 1을 framebuffer 1로 바꾸면 어떻게 될까?

SSH로 접속한 상태에서 Fluid Ardule 서비스를 멈추고 다음 명령을 실행했다.

sudo systemctl stop fluid_ardule.service
sudo con2fbmap 1 1
sudo chvt 1

놀랍게도 3.5인치 TFT에 진짜 Linux console이 나타났다.

Fluid Ardule의 메뉴도 아니고 Pillow로 렌더링한 운영 화면도 아니다. Raspberry Pi의 텍스트 콘솔이다. USB 키보드를 연결하면 명령어를 직접 입력할 수 있다. raspi-config도 실행할 수 있다.

다만 화면은 정확히 180도 뒤집혀 있었다.

사실 당연한 결과였다. Fluid Ardule의 TFT 설정에는 다음과 같은 항목이 있다.

dtoverlay=piscreen,spi0-0,rotate=90,speed=32000000,fps=30

여기서 rotate=90은 ILI9486의 기본 세로 방향 framebuffer를 Fluid Ardule이 사용하는 480×320 가로 화면으로 바꾸기 위한 것이다.

그런데 실제 Fluid Ardule에서는 케이스 내부의 커넥터와 케이블 배치를 편하게 하기 위해 TFT를 반대 방향으로 장착했다. 따라서 가로 화면은 맞지만 실제 사람이 보는 방향에서는 180도 뒤집혀 있다. Fluid Ardule 운영 스크립트는 Pillow로 렌더링한 화면을 다시 180도 회전하여 이를 보정한다.

Linux console은 당연히 이런 사정을 모른다.

그래서 /boot/firmware/cmdline.txt에 다음 커널 파라미터를 추가했다.

fbcon=rotate:2

재부팅 후 다시 console을 TFT에 연결했다.

이번에는 정상 방향이었다.


3.5인치 화면에 raspi-config를 띄워 보았다. 화면이 너무 작지 않을까 걱정했지만 의외로 아무 문제가 없었다. 메뉴를 읽고 조작하기에 충분했다.



그리고 다시 Fluid Ardule로 돌아오는 것도 간단했다.

sudo con2fbmap 1 0
sudo systemctl start fluid_ardule.service

잠시 뒤 익숙한 Fluid Ardule 화면이 다시 나타났다.

오늘은 Wi-Fi 설정 방법을 고민하다가 시작했다. 결론은 “굳이 모든 것을 Fluid Ardule UI 안에서 해결하려 하지 말자”였다.

그런데 그 과정에서 더 재미있는 가능성을 발견했다.

Fluid Ardule의 3.5인치 TFT는 악기 화면으로만 사용할 필요가 없다. 평소에는 Pillow 기반의 전용 악기 UI를 표시하다가, 필요할 때 서비스를 멈추고 Linux console로 전환할 수 있다. 설정이나 진단이 끝나면 다시 악기 UI로 돌아오면 된다.

이제 운영 스크립트에 필요한 것은 Wi-Fi 설정을 위한 복잡한 암호 입력 화면이 아닐지도 모른다. 단지 “Console Mode”로 들어가는 문 하나면 된다.

악기 UI는 악기답게 단순하게 유지하고, 시스템 관리는 Linux에게 맡긴다.

오늘은 기능 하나를 더 만든 날은 아니다. 오히려 만들지 않아도 될 기능을 찾아 헤매다가, 이미 시스템 안에 있던 다른 문 하나를 발견한 날이다.

2026년 7월 7일 화요일

완벽함의 유효기간은 생각보다 짧다

보다 정확히 말하자면 '완벽하다는 믿음의 유효기간은 생각보다 짧다'라고 하는 것이 맞을 것이다.

어제 수정한 Fluid Ardule 운영용 파이썬 스크립트(버전 260706b; 10,725줄)가 정말 완벽하게 작동하는 것 같았다. 

"이만하면 됐다!"

이제는 소개용 영상을 찍어서 유튜브에 올려도 손색이 없겠다고 자신감에 부풀어 있었다. Fluid Ardule의 프로토타입을 소개한 숏 영상은 나의 유튜브 채널에 몇 개 올라가 있지만, 본격적인 소개 영상은 정식으로 인클로저에 넣고 나서 테스트가 어느 정도 되면 그때 찍으려고 잔뜩 벼르고 있었다. 이번 주말에는 영상 작업이 가능하리라! 

하지만 완벽함에 대한 믿음은 단 한 시간도 가지 않았다. 260706b를 GitHub에 commit한 직후 테스트를 해 보다가 미처 점검하지 못한 곳에 오류가 남아 있음을 또 발견한다. 완벽이 아니었던 것이다.

완벽함의 유효기간은 왜 이렇게 짧을까?

때로는 세상이 바뀌어서 나의 완벽함에 대한 바깥의 기대 수준이 훌쩍 올라간 때문이기도 하다. 하지만 세상이 하루 사이에 갑자기 바뀌는 일은 많지 않다. 가장 근본적인 원인은 어제 느꼈던 완벽함이라는 것이 전적으로 나의 착각일 수도 있다는 것이다.

소프트웨어 개발이 막바지에 접어들면서 필요한 기능은 거의 다 구현이 된 상태에 이르렀다. 그러나 소위 fine-tuning에 이렇게 많은 시간이 소요될 것이라고는 미처 생각하지 못했다. 지금은 더욱 매끄럽고 안정적인 작동을 보장하기 위한 미세한 조정 단계이다. 파레토 법칙의 변주라고나 할까? 나머지 20%를 채우기 위해 80%의 노력을 들이고 있다.

조금 더 긍정적으로 말하자면, 그만큼 나도 성장했기에 과거에 완벽하다고 생각했던 것 사이에 숨어 있었던 부족함을 비로소 눈치채게 되었다는 뜻도 된다. 따라서 값진 시행착오를 딛고 조금씩 나아지는 과정을 밟게 된다. 

예를 들어 완벽하다는 믿음의 유효기간이 24시간에 불과하여 매일 고치고 또 부족함을 느끼기를 일주일 동안 반복했다고 치자. 그래서 점진적인 개선을 거쳐서 A->B->C...->H를 만들어 냈다고 가정하자. 일주일 간의 경험은 결코 시간 낭비가 아니다. B에 도달했기 때문에 더 나은 C를 만들기 위한 개선점이 비로소 보이게 되었다. 그러나 타인으로부터 '왜 단번에 H를 만들어내지 못했어? 그러면 완벽했다고 보고한 A는 도대체 뭐야? 그동안 뭐했어?'라고 비판을 받으면 모든 의욕이 꺾인다.

Fluid Ardule의 운영 스크립트는 나 혼자 재미로 하는 일이니 중간 과정에 실수가 좀 있더라도 누구로부터 시간이나 예산을 낭비했다는 말은 듣지 않는다. 점검은 전적으로 나 혼자 한다. 

수시로 현장 점검을 하지 않으면 우리가 하는 일을 믿지 못하겠다는 사람들이 있다. 오늘 오후에도 그 사람이 찾아온다고 한다. 참으로 반갑지 않다.

형편없었던 장마 중 달리기

늦은 장마로 비가 계속 내려서 7월 2일에 이번달의 첫 달리기를 한 뒤 삼일이나 쉰 다음 어제(6일) 다시 밖으로 나갔다. 토요일의 건강검진에서 장을 깨끗이 비우느라 너무 애를 쓴 탓일까, 또는 수면내시경을 위해 투여한 진정제의 부작용인 것일까, 주말 내내 침대를 벗어나지 못했다. 

그렇다면 삼일이나 달리기를 쉬는 동안 꽤 몸이 많이 회복되었을 법도 한데 어제의 5.5km 달리기는 정말 형편없는 수준이었다. 매번 집을 나설 때에는 '아, 이상하게 몸이 무겁네. 오늘은 3km만 뛸까?'하는 유혹에 시달린다. 어제는 더욱 그러하였다.


7.xkm를 달리고는 했던 과거를 돌이켜 보자. 아주 오랜 옛날도 아니고, 불과 1년 정도 전이다. 5km와 7.xkm는 적은 차이가 아니다. 요즘은 달리는 거리도 줄고 쉬는 날도 늘었는데 왜 과거보다 더 힘들다고 느끼는 것일까? 신체의 자연스런 노화 때문인 것인지, 보충 운동을 제대로 하지 않아서 그런 것인지. 

8월이 되면 달리기에 입문한지 딱 2년이 지난다. 무엇이 나아졌는지 아직도 잘 모르겠다. 쉬지 않고 어쨌든 5km는 한번에 뛸 수 있다는(페이스는 신경쓰지 않고) 것에만 만족해서는 안 될 터인데... 

2026년 7월 5일 일요일

정체불명 마이크로SD 카드의 쓸모 없음을 증명하다

명칭 풀네임 규격 용량 표준 파일시스템
microSD Standard Capacity, SDSC 최대 2GB FAT12 / FAT16
microSDHC High Capacity 2GB 초과 ~ 32GB FAT32
microSDXC eXtended Capacity 32GB 초과 ~ 2TB exFAT
microSDUC Ultra Capacity 2TB 초과 ~ 128TB exFAT

라즈베리 파이로 만든 Fluid Ardule은 이제 제법 안정적으로 작동한다. 어제는 소개용 영상을 제대로 찍으려고 배경지까지 구입하여 벽에 걸어 두었다. GitHub에는 지금까지 개발한 소스 코드와 문서가 전부 올라가 있다. 하지만 갑자기 마이크로SD 카드가 망가지면 어떻게 할 것인가? GitHub에 올려둔 설치 문서를 보고 따라서 하면 되지만 매우 번거롭다. 나의 프로젝트에 흥미를 느끼고 따라서 하려는 사람도 이와 같은 절차를 거쳐야 할 것이다. 그러나 개발자인 나 자신은 이보다는 좀 더 편하게 복구를 했으면 한다.

그래서 오늘은 현재 정상 작동 중인 Fluid Ardule 시스템의 비상 복구 이미지를 만들어 보기로 했다. 그리고 사운드폰트 등 내가 2차적 배포를 하면 라이선스상 문제가 될 만한 것은 제외한 이미지를 작은 용량으로 만들어서 배포한다면 Fluid Ardule이 널리 알려지는 데 도움이 될 것이다. 이를 어디에 올릴지는 고민을 해 봐야 되겠지만. 앞으로는 이미지 배포와 설치용 스크립트 개발 사이에서 고민을 하게 될 것 같다.

이를 위해서 주말 외출을 한 김에 오프라인 매장에서 32GB 마이크로SD 카드를 하나 구입했는데(아래 사진의 4번), 그렇게 현명한 구매 행위는 아니었던 것으로 판명되었다. 다음부터는 온라인에서 구입하리라. 1번은 현재 Fluid Ardule에서 사용 중이며, 3번의 카드는 Nano Ardule 드럼 패턴 플레이어(아두이노 나노)에 연결되어 있다.

수 시간 동안의 시행착오를 거친 끝에 내린 결론은 위 사진에서 2번으로 표시한 카드가 표면에 인쇄된 것으로는 '최고급 제품'처럼 보이지만, 실제 성능은 알 수 없다는 것이다. 2번과 4번을 동일한 방법으로 테스트하였으나 오직 4번에 써 넣은 복구용 이미지만 부팅 및 Fluid Ardule 작동에 성공하였다. 이미지를 쓰는 데에도 4번 카드가 훨씬 적은 시간이 걸렸다.

ChatGPT에게 표면의 마킹으로부터 최대한 제품의 성능을 추측해 보라고 하였다.

1번은 Samsung 32 GB EVO microSDHC입니다. 주황색 EVO 디자인의 비교적 구형 세대이고, 전면에 microSDHC / U1 표시가 보입니다. 즉 32 GB이므로 SDHC 계열이며, UHS Speed Class 1(U1) = 최소 지속 쓰기 10 MB/s 보장 등급입니다. 사진에는 UHS 버스의 I 표시(UHS-I)도 확인됩니다. 반면 요즘 카드처럼 A1/A2 또는 V30 표시는 없습니다. 2021년에 Pi 3B와 같이 샀다는 설명을 고려하면 Fluid Ardule의 원본 시스템 카드로 쓰인 이력이 매우 자연스럽습니다. 다만 2021년에 구입했다고 해서 2021년형 제품이라는 뜻은 아닙니다. 디자인상 더 이전 세대 제품일 가능성이 큽니다.

2번 OLEVO 32 GB는 재미있는 카드입니다. 전면에서 V10, A1, U1, UHS-I 표시가 모두 읽힙니다. 따라서 명목상으로는 Video Speed Class V10 = 최소 지속 쓰기 10 MB/s, Application Performance Class A1, U1 카드입니다. A1은 단순 동영상 저장보다 Raspberry Pi 같은 랜덤 I/O 환경에서 의미가 있는데, 규격상 최소 1500 read IOPS / 500 write IOPS 요구 조건을 갖습니다. 네 카드 가운데 표시된 규격만 놓고 보면 Raspberry Pi OS용으로 가장 ‘그럴듯하게 포장된’ 카드입니다. 문제는 말씀하신 대로 카드 소켓 모듈에서 인식 문제가 있었고 세 번 구입했다는 실제 경험이죠. 이것은 인쇄된 속도 등급과 전기적 호환성·컨트롤러 품질·카드 간 편차가 별개의 문제라는 좋은 사례입니다. 사진만으로 OLEVO의 제조사나 NAND/컨트롤러 출처는 판단할 수 없습니다.

3번은 SanDisk 32 GB microSDHC 구형 카드입니다. 검은색 전면이고 microSDHC / UHS-I 표시는 명확합니다. 오른쪽 아래 원형 안의 표시는 사진 해상도상 정확한 판독이 조금 애매합니다(자세히 보면 오른쪽이 열린 원 내부에 4가 기록되어 있어서 4MB/sec의 Speed Class를 의미함). 전면에 U1, A1, V10 등의 현대적인 성능 등급 표시는 보이지 않습니다. 따라서 네 장 중 외관 정보만으로는 성능을 가장 적게 알 수 있는 카드입니다. 아래쪽에 희미한 레이저 각인이 있고 MADE IN CHINA는 읽힙니다. 이 각인을 더 선명하게 접사하면 제품 코드나 제조 로트 일부를 추적할 가능성이 있습니다. 2025년 다이소 구입품이라는 점은 흥미로운데, 판매 시점과 카드 설계 세대가 상당히 다를 수 있음을 보여 줍니다.

4번은 SanDisk Ultra 32 GB microSDHC입니다. 전면에 Class 10의 원 안 10 표시, U1, UHS-I가 모두 보입니다. 따라서 최소 지속 쓰기 등급은 역시 10 MB/s 계열입니다. 최대 100 MB/s는 카드 전면에서는 확인되지 않고 구입 당시 제품 사양에 근거한 것으로 보입니다(포장재에 인쇄되어 있었음). 이 속도는 보통 최대 순차 읽기 속도이며 쓰기 속도 100 MB/s를 의미하지 않습니다. 사진상 A1/A2 표시는 보이지 않습니다.

U1, A1, V10 등은 Speed Class의 성능 등급을 표현하는 것이다. 단, UHS-I은 버스 인터페이스 세대를 뜻한다. Fluid Ardule(라즈베리 파이 3B)에는 삼성이나 샌디스크와 같이 신뢰할 수 있는 제조사의 A1 + UHS-I + 32GB 마이크로SDHC카드면 충분하다. 다나와에서도 SD카드 용어를 잘 정리하여 주었다.

그림 출처: SD Association Speed Class.

많은 시행착오 끝에 응급용 이미지를 만드는 방법을 정립하여 GitHub Fluid Ardule 프로젝트 사이트의 Fluid Ardule Disaster Recovery 문서에 기록해 두었다. 내용을 간단하게 요약해 보겠다.

32 GB 카드 전체를 dd로 복제하면 같은 ‘32 GB’ 카드라도 실제 섹터 수 차이 때문에 이미지가 들어가지 않을 수 있다. 그래서 image-utilsimage-backup을 이용하여 사용 중인 파일시스템만 담은 약 5.5 GB의 compact image를 만들고, image-check와 SHA-256 검증을 거쳤다.

이 이미지를 다른 microSD 카드(SanDisk Ultra 32GB, 위 카드 사진에서 4번)에 기록하여 Raspberry Pi 3B를 실제로 부팅했고, Fluid Ardule 실행과 오디오 출력이 잘 됨을 확인했다. 첫 부팅 뒤 루트 파일시스템도 대상 카드의 약 29 GB 전체 용량으로 자동 확장되었다. 즉 단순히 ‘백업 파일을 만들었다’는 데서 끝나지 않고, 다른 카드에서 실제 부팅까지 확인한 재난복구 이미지를 확보한 것이다.

이 과정에서 microSD 카드의 품질 차이도 직접 경험하였다. 같은 이미지를 기록해도 저가 카드(위 카드 사진의 2번 OLEVO)는 기록과 검증이 매우 느리고 결국 부팅하지 못한 반면, 새 SanDisk 카드에서는 훨씬 빠르게 기록되고 정상적으로 부팅이 되었다. 같은 32 GB라는 표기와 화려한 속도 등급이 카드의 신뢰성까지 보장하는 것은 아니었다.

오늘의 작업은 새로운 기능을 추가하는 개발은 아니었다. 오히려 지금까지 만든 것을 다시 살려낼 수 있는가를 확인하는 것이었다. 중국산 정체불명의 32GB 카드 하나가 자신의 쓸모없음을 증명하는 동안, Fluid Ardule에는 재난복구 절차가 확립되었다.

2026년 7월 4일 토요일

아르페지오의 속도를 조절하려 했는데, 범인은 에코였다

새벽 네 시에 일어나 앉아서 맛없는 음료를 벌컥벌컥 마신다. 몇 시간 뒤에 있을 대장 내시경 검사를 위해 장을 깨끗이 비우기 위함이다. 어젯밤 7시에 먹었던 1차 복용제는 그런대로 먹을 만했는데, 새벽 네 시에 먹어야 하는 2차 복용제는 정말 고역이다. 잠을 깬 김에 어제 퇴근후 벌어졌던 Fluid Ardule 운영 스크립트 개발기를 쓴다. 어차피 속이 그득하고, 잠시 뒤면 또 화장실을 들락거려야 하니 다시 잠자리에 들기는 틀렸다.

Fluid Ardule에서 요즘 흥미를 느끼는 것은 Yoshimi의 아르페지오 계열 음색(preset)이다. 자주 쓰다 보니 한 가지 아쉬움이 생겼다. 현재는 고정된 속도로만 일정 패턴의 note가 발생한다. 실제 곡의 템포에 따라 아르페지오 속도를 바꾸고 싶었다. Yomishi의 프리셋을 전환할 때 발생하는 잡음을 없애는 것이 가장 최근의 도전 과제였었다. 하나를 해결하면, 그 다음 문제에 몰두하게 된다.

아르페지오를 로드한 뒤 건반 하나를 누르면 음이 일정한 패턴으로 반복된다. 음색을 고르는 것만으로도 꽤 그럴듯한 연주가 된다. 그런데 연주 중에 조금 빠르게, 혹은 조금 느리게 바꾸고 싶다는 생각이 드는 것은 당연하다. Fluid Ardule에는 로터리 인코더가 있다. 이것을 돌려 아르페지오의 속도를 조절하면 좋겠다.

말은 간단하다. 문제는 Yoshimi에서 무엇을 건드려야 하는가였다. 당연히 BPM이라고 생각했다. 

AI(ChatGPT)에게 물었다. Yoshimi에는 명령행 인터페이스가 있으니 실행 중인 프로그램에 명령을 보내어 BPM을 바꿀 수 있지 않겠느냐고. 처음에는 AI도 그렇게 생각했다.

나는 Yoshimi 매뉴얼을 AI에게 주었다. AI는 매뉴얼을 읽고 다음과 같은 명령을 찾아냈다.

BPM <n>    default BPM if none from MIDI

좋다. 답을 찾은 것 같았다.

라즈베리 파이에서 Yoshimi를 인터랙티브 모드로 실행했다.

yoshimi -i

아르페지오 프리셋을 불러왔다.

load instrument /home/pi/sf2/yoshimi_links/Arpeggios__0001-Arpeggio1.xiz

그리고 BPM을 바꾸었다.

set bpm 60
set bpm 180

60과 180이면 세 배 차이다. 건반을 눌러 보았다.

똑같다.

나는 말했다.

이상한데요? bpm 바꾸어도 아르페지에이터 속도는 그대로예요.

AI는 매뉴얼을 다시 뒤졌다. 이번에는 LFO 항목에서 BPM 동기화 기능을 찾아냈다.

Bpm <s>    sync frequency to MIDI clock

아마 LFO가 BPM에 동기화되지 않은 상태라서 global BPM을 바꾸어도 소용이 없는 것 같다는 설명이었다. 그럴듯했다.

문제는 Yoshimi의 CLI가 생각보다 만만하지 않았다는 것이다.

set part 1

여기까지는 좋았다.

add

라고 입력했더니,

add what?

이라고 했다. set add라고 해야 했다. LFO로 들어가려고 lfo라고 입력했더니 또 알아듣지 못했다. set lfo라고 해야 했다.

Frequency context에도 들어갔다.

set frequency

마침내 원하는 장소에 도착했다.

@ p1+, A+, LFO freq+

여기에서,

set bpm on

을 실행했다. 다음과 같이 표시된다. 드디어 정확한 명령어 입력 방법을 알아낸 것이다.

Part 1 Kit 1 AddSynth Freq LFO BPM - on

이번에는 정말 되는 줄 알았다. BPM을 바꾸고 건반을 눌렀다.

똑같다. Rate도 바꾸어 보았다. 그러나 달라지는 것이 없었다.

AI는 또 다른 가능성을 제시했다. ADDsynth의 Voice Delay가 반복을 만드는 것이 아닐까? Voice 1과 Voice 2로 들어갔다. Delay라는 명령도 발견했다. 값을 바꾸었다. 나는 건반을 눌렀다.

전혀 안됩니다.

이날 오전 AI와 나의 대화에서 가장 많이 등장한 문장은 아마 이것이었을 것이다.

안 바뀝니다.

AI는 가설을 제시했다. 나는 라즈베리 파이에 명령을 입력했다. 건반을 눌렀다.

안 달라져요.

다시 가설. 다시 명령. 다시 건반.

빠르기와는 무관합니다!

이쯤 되자 매뉴얼에 나오는 일반적인 기능 설명만으로는 답을 찾기 어려워졌다. 나는 이미 분석을 위해 Yoshimi의 아르페지오 프리셋 파일을 AI에게 올려 둔 상태였다. 그래서 말했다.

아까 업로드했으니 다시 살펴봐요.

이번에는 매뉴얼이 아니라 실제 프리셋 파일 자체를 분석하기 시작했다. 대상은 이것이었다.

Arpeggios__0001-Arpeggio1.xiz

이름은 Arpeggio1이다. 나는 당연히 이 파일 어딘가에 아르페지에이터의 속도를 결정하는 파라미터가 있을 것이라고 생각했다. BPM, LFO, Rate, Clock 같은 것 말이다.

그런데 프리셋의 구조를 따라가던 AI가 다른 것을 지목했다.

Part 1. Effect 2. Echo.

에코?

나는 아르페지오의 속도를 바꾸고 싶은데 갑자기 에코라니. 솔직히 처음에는 이것도 별로 믿음이 가지 않았다. 테스트하는 내내 이미 여러 번 틀렸기 때문이다.

그래도 실험은 간단하다. Yoshimi CLI에서 Part 1로 들어갔다.

/
set part 1

Effect 2를 Echo context로 열었다.

set effect 2 echo

프롬프트가 바뀌었다.

@ p1+ eff 2 ECho-3?

Echo의 파라미터 중에는 Delay가 있었다. 값을 바꾸었다. 건반을 눌렀다.

와, 드디어 연주가 달라졌다.

BPM을 바꾸고, LFO를 뒤지고, Voice Delay를 건드려도 꿈쩍하지 않던 반복 속도가 Echo Delay 값을 바꾸자 확연히 달라졌다.

우리가 찾던 아르페지오의 속도는 에코가 만들고 있었다.

물론 엄밀히 말하면 "아르페지에이터가 에코였다"는 표현은 정확하지 않을 것이다. 그러나 적어도 내가 사용하던 Yoshimi의 Arpeggio1 프리셋에서 귀에 들리는 반복 패턴의 속도를 실질적으로 좌우하는 파라미터는 Part 1 Effect 2의 Echo Delay였다.

이제 원인을 찾았다. 다음 문제는 Fluid Ardule의 화면에 무엇을 표시할 것인가였다.

Echo Delay 42

이렇게 표시할 수는 없다. 연주하는 사람이 알고 싶은 것은 Yoshimi 내부의 이펙트 파라미터 값이 아니다. 대략 얼마나 빠르게 반복되는가이다.

처음에는 BPM과 비슷한 숫자를 만들어 Echo Delay에 대응시키는 간단한 식을 만들었다.

echo_delay = round(6000 / raw_speed)

그리고 작은 Python 테스트 프로그램(test_yoshimi_arp_speed_calibrated.py, GitHub에 공개)을 만들었다. 숫자를 넣고 건반을 연주했다. 메트로놈과 비교하여 실제로 어느 정도의 BPM처럼 들리는지 측정했다.

처음 측정값은 조금 들쭉날쭉했다. 그래서 다시 측정했다.

60  → 52
75  → 66
100 → 83
120 → 100
140 → 126
160 → 133
180 → 140
200 → 162
220 → 181
240 → 200

정밀한 계측 장비를 쓴 것은 아니다. 내 귀와 메트로놈이다. 그래도 관계는 꽤 일정했다.

AI에게 계산을 시켰다. 단순 선형 회귀 결과는 다음과 같았다.

apparent_bpm ≈ 0.797 × raw_speed + 5.13

그러면 역으로 원하는 체감 속도에서 내부 값을 계산할 수 있다.

raw_speed ≈ (display_bpm - 5.13) / 0.797

그리고 이것을 다시 Echo Delay 값으로 변환한다.

echo_delay = round(6000 / raw_speed)

첫 번째 테스트 프로그램은 측정을 위한 것이었다. 측정이 끝난 뒤 AI에게 그 결과를 주고 프로그램을 한 번 고쳤다. 보정된 테스트 프로그램으로 다시 확인했다. 괜찮았다.

그제야 Fluid Ardule 본 프로그램에 넣었다.

이 기능의 이름을 BPM이라고 하지는 않았다. 진짜 BPM이 아니기 때문이다. MIDI clock과 동기화된 값도 아니다. 특정 Yoshimi 프리셋의 반복 속도를 귀로 측정하고 경험식으로 보정한 값이다.

그래서 이름은,

Arpeggio Speed.

인코더를 돌리면 1씩 변한다. 연주 중에도 바로 속도가 달라진다. 화면 오른쪽에는 작은 글씨로 이렇게 표시했다.

Rotate Encoder to adjust

기능 하나를 추가하는 데 오전 한나절이 걸렸다.

처음에는 내가 매뉴얼을 AI에게 주었다. AI가 매뉴얼을 분석하여 BPM을 찾았다. 틀렸다. 다시 매뉴얼에서 LFO BPM sync를 찾았다. 틀렸다. Voice Delay를 의심했다. 또 틀렸다.

결국 내가 이미 올려 둔 실제 프리셋 파일을 AI가 분석했다. 그 안에서 Echo를 찾아냈다. 나는 라즈베리 파이에서 CLI 명령을 하나씩 입력하고 건반을 눌러 검증했다. 마지막에는 테스트 프로그램을 만들고, 메트로놈으로 직접 속도를 재고, 측정값을 AI에게 주어 회귀식을 만들었다. 이를 바탕으로 Fluid Ardule 운영 스크립트를 최종적으로 수정하였다. 상세한 기술적인 내용은 GitHub에 Controlling the Apparent Arpeggio Speed of Yoshimi Presets라는 제목으로 따로 정리하였다.

요즘 AI와 하는 개발은 대략 이런 식이다.

실은 이 글도 첫 단락을 제외하면 AI가 써 준 것을 거의 그대로 옮긴 것이다. Fluid Ardule 운영 스크립트 개발을 위해 ChatGPT와 작업한 대화창은 나의 시행착오를 전부 기억하고 있기 때문에, 블로그 작성용 초안을 달라고 명령만 하면 이렇게 뚝딱 만들어 낸다. 처음에는 이런 방식으로 글을 쓰는 것에 대하여 상당한 거부감을 느꼈었는데, 나 역시 편리함과 효율 앞에서는 최신 기술과 적당히 타협하지 않을 수가 없다.

2026년 6월 30일 화요일

개발은 마지막 5분에 끝난다?

Yoshimi synth
그림 출처: Yoshimi synth

어제의 퇴근 후 개발은 Yoshimi를 매끄럽게 작동하기 위한 투쟁이었다. Yoshimi에 대한 ChatGPT의 설명을 인용해 보자.

Yoshimi는 Linux 환경을 위한 오픈소스 소프트웨어 신시사이저로, SoundFont를 재생하는 FluidSynth와 달리 실시간 음색 합성을 통해 소리를 만들어 낸다. Additive, Subtractive, PadSynth 등 다양한 합성 방식을 지원하며, 풍부한 패드, 리드, 베이스, 아르페지오와 같은 신디사이저 음색에 특히 강점을 가진다.

Fluid Ardule에서는 SoundFont(FluidSynth)뿐 아니라 Yoshimi도 하나의 음원 엔진으로 사용할 수 있다. 그런데 악기를 바꿀 때마다 Yoshimi를 다시 시작해야 했고, 그때마다 "붕~" 하는 짧은 소리가 났다. 실사용에는 매우 거북한 상황이었다.

처음에는 당연히 Python 코드의 문제라고 생각했다. 운영 스크립트를 이리저리 고쳐 보았고, 실행 중인 Yoshimi에 명령을 보내 악기만 교체하는 방법도 시도했다. 화면은 정상적으로 바뀌었지만 정작 소리는 바뀌지 않았다. 결국 그 방법은 폐기했다.

여기까지였다면 "Yoshimi는 원래 그런가 보다." 하고 끝냈을지도 모른다. 일단 다른 쪽으로 UI를 안정화한 파이썬 운영 스크립트의 최신 버전을 커밋한 다음 5km 야간 달리기를 하고 돌아왔다.

운동을 하고 돌아오니 정신은 더욱 맑아졌다. 이대로 잠자리에 들기에는 아까웠다. 다시 노트북 컴퓨터 앞에 앉아 커맨드 라인에서 Yoshimi의 프리셋 변경 테스트를 실시해 보았다.

놀랍게도 실행 중인 Yoshimi에서도 다음과 같은 명령으로 악기를 바꿀 수 있었다.

load instrument /path/to/file.xiz

그런데 이상한 점이 있었다. 공백이 없는 파일은 잘 바뀌는데, 공백이 들어 있는 파일 이름만 계속 실패하는 것이다.

한참을 테스트한 끝에 원인을 찾았다. Yoshimi의 CLI는 쉘(shell)이 아니다. 따옴표도, 백슬래시도 일반적인 리눅스 셸처럼 해석하지 않는다. 결국 공백이 없는 심볼릭 링크를 만들어 그 경로를 전달하자 실행 중인 Yoshimi의 패치가 즉시 바뀌었다.

아직 Fluid Ardule에 적용한 것은 아니다. 하지만 오늘 얻은 것은 훨씬 더 중요하다.

"실행 중인 Yoshimi의 패치를 바꾸는 것은 가능하다."

그동안은 재시작이 필수라고 생각했지만, 이제는 부드럽게 전환할 수 있는 길이 보이기 시작했다.

개발을 하다 보면 가끔은 몇 시간 동안 한 발짝도 앞으로 나가지 못하는 것처럼 느껴진다. 그런데 하루를 접고 운동을 하고 돌아와 마지막 5분 동안 결정적인 단서를 발견하는 경우가 있다.

그래서 나는 요즘 이런 생각을 한다.

개발은 하루 종일 하는 것이지만, 진짜 해결은 마지막 5분에 이루어지는 경우가 많다.

더불어서 이런 깨달음도 있다. 어제까지 만든 것이야말로 정말 최선의 안정화 버전이라고 생각했는데, 오늘 다시 돌이켜 보면 "이렇게 부끄러운 것을 어떻게 세상에 내어 놓겠는가" 하는 생각이 든다는 것이다. 운영 스크립트에 거는 기대 수준은 나날이 올라가고 있으며, 개선에 드는 시간도 생각보다 점점 짧아지는 느낌이다.

빨리 소개용 동영상을 찍고 싶은데, 내일 아침 일찍 서울에서 열리는 회의에 참석하기 위해 하루 먼저 올라와 서울역 근처의 허름한 호텔에서 밤을 보내는 내가 조금은 처량하게 느껴진다.


2026년 7월 2일 업데이트

공백을 포함한 Yoshimi의 프리셋 위치를 하이픈으로 대체하여 심볼릭 링크를 만든 뒤 Fluid Ardule 운영 스크립트 내에서 변경을 시도하였으나 소리가 바뀌지 않았다. Yoshimi를 커맨드 라인에서 실행하여 자체 프롬프트에서 load instrument를 실행하는 것과, Fluid Ardule에서 제어하는 것은 약간 다른 것 같다. 일단 이 문제는 다른 방식으로 우회하여 해결하였다. Yoshimi에서 볼륨을 줄여서 붕~ 소리가 거의 나지 않게 만든 뒤 다른 프리셋으로 바꾼 다음 다시 음량을 원상복구하는 간접적인 방식이었다. 일종의 편법이지만 한결 나아졌다.


2026년 7월 3일 업데이트

어제 퇴근 후 작업한 26072f 버전에서 드디어 안정적인 Yoshimi 패치 변경에 성공하였다. 악기 변경 전후에 볼륨을 줄였다가 원상복구하는 편법도 더 이상 필요하지 않다. 작동 안정성도 더욱 좋아진 것 같다.

2026년 6월 29일 월요일

DIYer가 가장 하기 싫은 것은...

사람마다 다르겠지만, 나는 무엇인가를 자르고 뚫는 일이 가장 하기 싫다. 특히 전동 공구를 쓸 때에는 시끄럽고 사고가 나기 쉬우며, 수공구로 톱질이나 줄질을 하다가도 손을 다칠 수 있다. 알루미늄 판에 애써 구멍 위치를 표시하고 타공을 마쳤는데 정작 여기에 고정할 보드의 볼트 구멍 위치가 맞지 않을 때의 그 절망감은 느껴 본 사람만이 안다.

반면 단단하고 창백한 실납이 인두의 열기에 녹으면서 광택과 함께 부드럽게 흐를 때에는 일종의 희열을 느낀다. 하얗게 피어오르는 연기 또한 시각적 즐거움을 더한다. 흡연자의 기분이 이런 것일까? 어쩌면 DIY 작업 중 건강에 가장 해로울 수도 있는 납땜 작업이 나는 가장 즐겁다. 물론 열을 너무 많이 가해서 배선 피복이 녹거나, 만능기판의 동그란 패드가 떨어져 나갈 때 그 난처함은 이루 말할 수 없지만. 간혹 달아오른 인두에 손을 데기도 한다.

드릴 스탠드를 구한 이후로 구멍 뚫기 작업은 한결 수월해졌다. 드릴을 수직으로 움직이는 것이 가능해졌기 때문이다. 작업대에 스탠드를 고정해 두고 작업물까지 물린 바이스까지 있다면 금상첨화일 것이다. 아직은 작업물 + 드릴 방아쇠 + 드릴을 내리누르는 손잡이까지 한꺼번에 붙잡아야 해서 거의 서커스 수준의 요령이 필요하다. 

드릴 작동 및 속도 조절을 발로 할 수 있다면? 조광기를 이용한 드릴 속도 조절기를 만들었던 일이 있다. 이는 R-core 출력트랜스포머(진공관앰프용)의 권선기로 쓰기 위함이었다. 다음은 그 증거 사진(원본 글 링크; 2022년도에 작성)이다. 사진 배경을 보니 광화문 인근 오피스텔에서 파견 근무를 하던 시절 찍은 것이다. 그 좁은 방구석에서도 열심히 납땜을 하고 구멍을 뚫었었다.


혹시 여기에 악기용 익스프레션 페달을 연결하면 발로 속도를 조절하는 것이 가능할까? 조광기는 상용 220V 전기를 사용하는 것이므로, 저전압에서 작동하는 포텐셔미터에 불과한 익스프레션 페달을 그대로 연결할 수는 없다. 안전을 보장할 수 있는 추가 회로를 만들어야 한다.

차라리 드릴 프레스 손잡이에 끈을 달아서 발에 건 뒤 아래로 당기는 것이 더 나을지도 모르겠다. 간단한 것이 최고 아닌가? 

밤 8시가 지난 시각, 아랫집에 미안한 마음을 느끼면서 라즈베리 파이 케이스에 다섯 개의 구멍을 뚫고 줄질을 하였다. RCA 단자를 쇠톱으로 자르는 일은 매우 쉬웠다. 플라스틱이니까.

헤드폰 앰프 만들기. 배선을 완료한 뒤 포맥스 판을 잘라서 위를 덮으면 끝난다. 작업대가 너무 지저분하여 AI로 배경을 약간 정리하였다.

개조한 라즈베리 파이 케이스는 헤드폰 앰프(MAX4410 칩 사용; 데이터시트)의 케이스로 변모하였다. 케이스의 바닥쪽 판은 라즈베리 파이 3B와 함께 Fluid Ardule 안에 영구 장착되었다. 하나의 케이스가 두 개의 작품으로 나뉘어 새 삶을 얻은 셈이다. 

2026년 6월 27일 토요일

Fluid Ardule의 운영 스크립트가 드디어 1만 줄을 돌파하다

경주 화백컨벤션센터(HICO)에서 열렸던 2026년 한국미생물생명공학회 정기학술대회 및 국제심포지엄을 다녀왔다. 지난 몇년 동안은 홍보를 위한 세션에서 짤막하게 발표를 하고 서둘러 돌아와서 다른 회의 일정을 소화했었지만, 이번에는 정말 오랜만에 여유를 가지고 마지막 plenary lecture(연세대학교 이봉신 교수, Human-Data Interaction for Exploration and Communication)까지 알뜰하게 듣고 돌아왔다.



이봉신 교수가 마이크로소프트 리서치에서 일할 때 개발한 Data Formulator는 AI를 이용해 데이터를 시각화하는 강력한 도구이다. 자연어 입력만으로 원하는 목표를 달성하는 것은 쉽지 않다. UI 상호작용과 자연어 입력을 결합한 방식을 채택하여 복잡한 데이터의 시각화를 할 수 있으며, 이는 새로운 수준의 질문으로 이어진다. Data Formulator는 MIT License로 전환되어 누구나 사용할 수 있게 되었다. 그렇다. 데이터의 시각화는 화려함을 자랑하기 위함이 아닌 것이다. 

이런 수준의 챠트를 그리기 위해 R 패키지를 찾아서 설치하면서 얼마나 열심히 공부를 해야 했던가? 확실히 세상은 달라졌다. AI가 새로운 기회를 주고 있으며 일상 주변에서 의미와 재미를 찾는데 큰 도움을 주고 있다. 오늘은 AI에 대해서 조금은 긍정적인 생각을 해 본다. 

이렇게 경주에서 많은 영감을 얻고 돌아왔다.







주말에는 다시 Fluid Ardule 개발 작업이 이어졌다. 흔한 목공용 나사못이 아니라 thumb screw를 이용하여 아크릴 상판을 고정하도록 만들었다. 거추장스럽게 길었던 GPIO 확장용 리본 케이블도 적당한 길이의 것으로 바꾸었다. M4 thumb screw에 물릴 삽입용 황동 너트는 원래 열을 가해서 플라스틱 재료에 고정하는 용도이다. 많은 힘을 받는 곳이 아니기 때문에 너트의 직경보다 약간 작은 구멍을 6mm 드릴날로 뚫은 뒤 목공본드를 발라서 박아 넣었다.


이 부품을 구입해 놓고서도 과연 잘 장착할 수 있을지 고민이 많았었다. 그냥 하면 된다! 판재 정중앙 위치에 맞추어 박아 넣지는 못하였지만...

생각보다 멋지다. 상판을 언제든지 쉽게 열어서 유지보수를 할 수 있게 되었다. 뿐만 아니라 소개용 비디오를 촬영하기에도 손색이 없는 외관을 갖추었다.

오늘의 개발을 통해 Fluid Ardule 운영 스크립트(launch_fluidardule.py)는 드디어 1만 줄을 넘어서게 되었다. "이 정도면 파일을 분리해야 하는 것 아닌가?"라는 생각이 자연스럽게 든다. 하지만 프로그램의 규모를 줄 수만으로 판단할 문제는 아닌 것 같다.

이 운영 스크립트는 하나의 이벤트 루프를 중심으로 화면, 버튼, MIDI, 오디오 엔진, USB 장치, 인터넷 라디오, Combi, 미디어 플레이어가 서로 긴밀하게 상호작용하는 일종의 펌웨어(firmware)에 가깝다. 오늘만 해도 USB 핫플러그, 볼륨의 Soft Takeover, Combi의 UI 흐름을 함께 다듬었는데, 만약 이 기능들이 여러 개의 작은 파일에 흩어져 있었다면 오히려 전체적인 사용자 경험을 일관성 있게 개선하기 어려웠을 것이다.

물론 언젠가는 독립성이 높은 기능들을 분리해야 할 날이 올 것이다. 그러나 지금은 줄 수보다 결합도(coupling)가 더 중요한 기준이라는 생각이 든다. 아직은 하나의 운영 스크립트 안에서 전체 시스템의 동작을 한눈에 바라보는 편이 Fluid Ardule라는 악기를 다듬는 데 더 적합하다.