Ardule Drum Pattern System에서 사용하는 2-bar 드럼 패턴의 텍스트 표현 포맷이다. ADT v2.2는 ADP v2.2 바이너리 캐시 포맷과 1:1 대응되며, 사람이 읽고 편집하기 쉬운 것을 목표로 한다.
드럼 머신이 출현하면서 드럼 연주 패턴을 그리드 형태로 표현하는 것은 매우 자연스러운 일이 되었다. ADT는 이를 텍스트로 표현한 것에 해당한다. 다음 자료의 출처인 단행본(260 Drum Machine Patterns)을 스캔한 PDF 파일은 인터넷을 잘 뒤지면 나온다. MIDI 파일로 만들어 놓은 것도 있다!(Cakewalk discussion) 아래 다이어그램에서 맨 위 row의 AC는 accent를 말하며, 특정 스텝에 전부 작용한다. 전통적인 그리드 포맷에서 각 row는 악기(slot)에 해당하지만, ADT에서는 이를 90도 돌려서 step으로 나타낼 수도 있다. 컴퓨터 입장에서는 이게 더 자연스럽다.
ADT v2.2 파일은 다음과 같이 구성된다.
예)
; ADT v2.2 NAME=ROCK01_MAIN TIME_SIG=4/4 GRID=16 LENGTH=32 SLOTS=12 KIT=GM_STD ORIENTATION=STEP SLOT0=KK@36,KICK SLOT1=SN@38,SNARE SLOT2=CH@42,HH_CL ... SLOT11=PH@44,HH_PED X..X..X..X..X..X..X..X.. ....X.......X.......... ........................ ...
모든 헤더 필드는 `KEY=VALUE` 형식이며, 대소문자를 구분하지 않는다. 미지의 키는 무시된다.
| 키 | 필수 여부 | 형식 / 예시 | 설명 |
|---|---|---|---|
| NAME | 필수 | `NAME=ROCK01_MAIN` | 패턴 이름(ASCII/UTF-8 문자, 공백 허용). |
| TIME_SIG | 필수 | `TIME_SIG=4/4` | 박자표. 재생 타이밍에는 영향 없음. |
| GRID | 필수 | `GRID=16` / `8T` / `16T` | 패턴 해상도. |
| LENGTH | 필수 | `LENGTH=32` | 전체 스텝 수(정수). |
| SLOTS | 필수 | `SLOTS=12` | 슬롯 수. ADP v2.2 표준은 12를 가정. |
| KIT | 필수 | `KIT=GM_STD` | 드럼 킷 이름(문자열). |
| ORIENTATION | 선택 | `ORIENTATION=STEP` | STEP 또는 SLOT. 생략 시 자동 판정. |
각 슬롯은 MIDI 노트 번호, 약어, 이름으로 정의한다. 키 이름은 `SLOT0`부터 `SLOT11`까지를 표준으로 한다.
형식:
SLOTn=ABBR@NOTE[,NAME]
예)
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
헤더와 SLOT 선언 이후부터 파일 끝까지는 “본문 패턴” 영역이다. 빈 줄 또는 세미콜론(;)으로 시작하는 줄은 코멘트로 취급하여 무시한다.
본문에서 사용할 수 있는 문자는 다음과 같다.
| 문자 집합 | ACC 값 | 의미 | |
|---|---|---|---|
| `-` | 0 | rest / hit 없음 | |
| `.` | 1 | 약박 | |
| `o`, `O` | 2 | 중간강 | |
| `x`, `X`, ` | ` | 3 | 강박 |
예) GRID=16, LENGTH=32, SLOTS=12
X..X..X..X..X..X..X..X.. ....X.......X.......... ........................ ...
예) SLOTS=12, LENGTH=32
X..X..X..X..X..X..X..X.. ; SLOT0 ....X.......X.......... ; SLOT1 ........................ ; SLOT2 ...
ADT v2.2 → ADP v2.2 변환기에서는 내부적으로 항상 STEP 오리엔테이션으로 변환한 뒤, ADP를 생성한다.
ADT v2.2는 여러 개의 패턴을 하나의 파일로 묶는 컨테이너 형식(ADX)을 지원한다.
ADT v2.2는 ADP v2.2 바이너리 캐시와 1:1 대응한다.
ADT v2.2 사양에서는 SWING, TEMPO를 별도의 헤더 필드로 정의하지 않는다. 이 필드는 ADP v2.2 헤더 레벨에서만 존재하며, 현재 구현에서는 모두 0으로 저장된다.
ADT v2.2 파일을 생성하거나 읽을 때 다음을 확인한다.
이 사양은 현재 제공되는 `mid2adt.py` 및 `adt2adp.py` 스크립트와 호환되며, Ardule Drum Pattern Player v2.3/2.4에서 사용할 ADP v2.2 캐시 파일 생성의 기준으로 삼는다.
work\ ├─ 01_input_MID\ # 입력 MIDI 파일 ├─ 02_MID\ # 2마디 MIDI 세그먼트들 (straight) ├─ 03_MID_TRIP\ # 2마디 MIDI 세그먼트들 (triplet) ├─ ADT\ # 변환된 ADT (백업/편집용) ├─ SD\ │ ├─ PATTERNS\ # 최종 ADP만 (장치가 읽을 폴더) │ ├─ SONGS\ # ARR/APT (곡 구성) │ └─ SYSTEM\ # INDEX.TXT, SETTINGS.CFG ... └─ tools\ # mid2report_integrated.py, midi2adt.py, adt2adp.py, mkindex.py
02_MID와 03_MID_TRIP는 사실 별로 필요하지 않다.
8.3 포맷의 파일명을 갖춘 type 0 MIDI 파일로서 GM 드럼킷에 해당하는 note number(35~81)를 갖고 있어야 한다. mid_check.py는 옵션으로 지정한 디렉토리 내의 모든 MIDI 파일을 스캔하여 점검한다. 파일명을 8.3으로 바꾸거나 type 0으로 전환하는 기능도 갖고 있다.
> python.exe ..\..\tools\mid_check.py
name,size_bytes,format,ntrks,division,duration_sec,is_8dot3,basename_is_numeric,uses_channel_10,note_on_count,time_sigs,tempos_bpm,ch10_note_min,ch10_note_max,ch10_bad_drum_notes
12bar1.mid,1497,0,1,480,24.002,True,False,True,210,4/4,120.0,36,52,
12bar4.mid,1179,0,1,480,24.002,True,False,True,157,4/4,120.0,36,52,
12bar6.mid,1605,0,1,480,24.0,True,False,True,228,4/4,120.0,36,52,
12bar7.mid,1785,0,1,480,24.0,True,False,True,259,4/4,120.0,36,52,
2AFROCUB.MID,2694,0,1,240,70.441,True,False,True,414,4/4,102.0,36,50,
...중략...
world7.mid,3133,0,1,480,29.48,True,False,True,410,4/4,130.0,25,42,"25,29"
Summary:
{
"files": 156,
"bad_headers": 0,
"formats": {
"0": 142,
"1": 14
},
"uses_ch10_count": 156,
"total_duration_sec": 10484.821
}
GM Drum range check (channel 10, notes 35–81):
[GM-DRUM-RANGE] Latin6.mid: channel 10 notes outside 35–81 -> [82]
[GM-DRUM-RANGE] dance19.mid: channel 10 notes outside 35–81 -> [27, 102, 107]
[GM-DRUM-RANGE] dance21.mid: channel 10 notes outside 35–81 -> [94, 102, 107]
[GM-DRUM-RANGE] dance3.mid: channel 10 notes outside 35–81 -> [26, 30]
[GM-DRUM-RANGE] dance34.mid: channel 10 notes outside 35–81 -> [33]
[GM-DRUM-RANGE] dance4.mid: channel 10 notes outside 35–81 -> [22, 26, 30]
[GM-DRUM-RANGE] dance42.mid: channel 10 notes outside 35–81 -> [30, 32, 34]
[GM-DRUM-RANGE] dance8.mid: channel 10 notes outside 35–81 -> [24, 28]
[GM-DRUM-RANGE] world13.mid: channel 10 notes outside 35–81 -> [24, 26, 28, 96, 101]
[GM-DRUM-RANGE] world18.mid: channel 10 notes outside 35–81 -> [91]
[GM-DRUM-RANGE] world23.mid: channel 10 notes outside 35–81 -> [104]
[GM-DRUM-RANGE] world7.mid: channel 10 notes outside 35–81 -> [25, 29]
드럼 패턴을 그리드 형태로 표현하여 A4 용지 크기의 PDF로 출력해 보자. Break로 취급해야 할 곳을 어디인지를 파악하는데 도움이 될 것이다. 실제 연주를 들어보려면 적당한 시퀀서 또는 DAW에 로드하는 것이 정답이지만, 보다 간단하게는 온라인 도구인 html-midi-player를 써도 좋다.
> python.exe ..\tools\midi_drum_grid_multiline_pdf.py .\2BLUES.MID [OK] Saved: 2BLUES_grid.pdf
출력된 결과 샘플: 2blues_grid.pdf
하나의 MIDI 파일을 상세하게 분석하려면 mid2report_integrade.py를 이용한다. 화면으로 길제 출력물이 나오므로 다음의 사례에서는 텍스트 파일로 리다이렉션하는 사례를 보여준다.
> python.exe ..\tools\mid2report_integrated.py .\2BLUES.MID | Out-File analysis.txt
출력된 결과 샘플: analysis.pdf </code>
Triplet 여부도 이 스크립트를 통해서 판별할 수 있다.
grid : triplet (triplet_hit=1.0, straight_hit=1.0)
.\00_orig_MIDI_files 하위의 모든 .mid 파일에 대해 화면으로 출력되는 분석 결과 중 straight/triplet 라인만 추출하여 mid_triplet_report.csv 파일로 저장하기.
ls .\00_orig_MIDI_files\*.mid | % {
$name = $_.Name
$line = python .\tools\mid2report_integrated.py $_.FullName | Select-String "grid"
if ($line -and $line.Line -match 'grid\s*:\s*(\w+)') {
[PSCustomObject]@{
File = $name
Grid = $Matches[1]
}
}
} | Sort-Object Grid, File | Export-Csv mid_triplet_report.csv -NoTypeInformation
ADT 파일을 만드는 가장 중요한 입력물인 2-bar pattern을 만드는 것은 split_drums_2bar_save.py이다. 본격적으로 MIDI 파일을 분할하기 전, --print-genre-only 옵션을 주면 원본 .MID 파일의 이름으로부터 장르를 유추한 뒤 다음과 같이 패턴명에 삽입할 수 있는 3글자 약자를 만든다. 장르 매핑 정보는 지금도 계속 업데이트 중이다. 지나치게 세분화하는 것은 좋지 않을 것이다.
| 코드 | 매칭 키워드 (파일명 내) | 장르 풀네임 |
|---|---|---|
| RCK | rock | Rock |
| BOS | bossa, bossanova | Bossa Nova |
| FNK | funk | Funk |
| JZZ | jazz | Jazz |
| BLU | blues, blue | Blues |
| LAT | latin | Latin |
| SMB | samba | Samba |
| WLZ | waltz, wlz | Waltz |
| SWG | swing, swg | Swing |
| SHF | shuffle, shf | Shuffle |
| REG | reggae | Reggae |
| MTL | metal | Metal |
| HHP | hip hop, hip-hop, hiphop, hhp | Hip Hop |
| HSE | house, hse | House |
| TNO | techno, tno | Techno |
| DRM | (기본값: 어떤 키워드에도 매칭되지 않을 때) | Generic Drum / Default |
> python.exe ..\tools\split_drums_2bar_save.py .\2BALLAD.MID --print-genre-only [GENRE] Inferred from filename '2BALLAD.MID' : BAL
실제 분할 작업에 들어가 보자. 기본 동작은 덮어쓰기이므로 동일 장르에 대하여 새로 만들어지는 패턴 번호를 지정하려면 --start START로 인덱스 번호를 주어야 한다. 장르 또한 자동 검출이 기본이나 지정해도 된다. 한 파일을 분할하여 만들어지는 모든 패턴은 동일한 장르가 된다.
> python.exe ..\tools\split_drums_2bar_save.py .\2BALLAD.MID --export-grid --grid-pdf
Genre inferred from filename: BAL
=== 2-bar slicing report for 2BALLAD.MID ===
Ticks per beat : 240
Initial time sig : 4/4
Bar ticks : 960
Total ticks : 28800
Total bars (floor) : 30
Used bars (2-bar xN): 30
Dropped full bars : 0
Tail remainder : 0 ticks beyond full bars
Saved slice 0 (bars 1-2) -> BAL_P001.MID
Grid PNG saved: BAL_P001_grid.png
Saved slice 1 (bars 3-4) -> BAL_P002.MID
Grid PNG saved: BAL_P002_grid.png
Saved slice 2 (bars 5-6) -> BAL_P003.MID
Grid PNG saved: BAL_P003_grid.png
Saved slice 3 (bars 7-8) -> BAL_P004.MID
Grid PNG saved: BAL_P004_grid.png
Saved slice 4 (bars 9-10) -> BAL_P005.MID
Grid PNG saved: BAL_P005_grid.png
Saved slice 5 (bars 11-12) -> BAL_P006.MID
Grid PNG saved: BAL_P006_grid.png
Saved slice 6 (bars 13-14) -> BAL_P007.MID
Grid PNG saved: BAL_P007_grid.png
Saved slice 7 (bars 15-16) -> BAL_P008.MID
Grid PNG saved: BAL_P008_grid.png
Saved slice 8 (bars 17-18) -> BAL_P009.MID
Grid PNG saved: BAL_P009_grid.png
Saved slice 9 (bars 19-20) -> BAL_P010.MID
Grid PNG saved: BAL_P010_grid.png
Saved slice 10 (bars 21-22) -> BAL_P011.MID
Grid PNG saved: BAL_P011_grid.png
Saved slice 11 (bars 23-24) -> BAL_P012.MID
Grid PNG saved: BAL_P012_grid.png
Saved slice 12 (bars 25-26) -> BAL_P013.MID
Grid PNG saved: BAL_P013_grid.png
Saved slice 13 (bars 27-28) -> BAL_P014.MID
Grid PNG saved: BAL_P014_grid.png
Saved slice 14 (bars 29-30) -> BAL_P015.MID
Grid PNG saved: BAL_P015_grid.png
[grid-pdf] Saved high-res two-column PDF: BAL_grids_A4_2col_big.pdf
[grid-pdf] Running Ghostscript for A4 resize:
C:\Program Files\gs\gs10.06.0\bin\gswin64c.EXE -sDEVICE=pdfwrite -o BAL_grids_A4_2col.pdf -dDEVICEWIDTHPOINTS=595 -dDEVICEHEIGHTPOINTS=842 -dFIXEDMEDIA -dPDFFitPage -dNOPAUSE -dBATCH BAL_grids_A4_2col_big.pdf
GPL Ghostscript 10.06.0 (2025-09-09)
Copyright (C) 2025 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
Processing pages 1 through 2.
Page 1
Page 2
[grid-pdf] Saved resized A4 PDF: BAL_grids_A4_2col.pdf
--export-grid 옵션은 모든 패턴에 대해 다음과 같은 그리드 이미지를 만든다. 패턴을 시각적으로 비교하기에 아주 편리할 것이다. --grid-pdf 옵션은 모든 2-bar 패턴의 그리드를 하나로 모아서 여러 페이지의 PDF로 만들어 준다. 12개의 slot은 사전에 지정되어 있지만 이 범위를 벗어나는 것은 GM drum kit에 맞춘 노트 넘버로 표현된다. Triplet인 경우 자동으로 검출하여 12 step / bar로 만들어 준다.
| 슬롯 | 약자 | GM 드럼 노트 | 설명 |
|---|---|---|---|
| 0 | BD | 35, 36 | Bass Drum (Kick) |
| 1 | SD | 38, 40 | Snare Drum |
| 2 | LT | 41, 43 | Low Tom 계열 |
| 3 | MT | 45, 47 | Mid Tom 계열 |
| 4 | HT | 48, 50 | High Tom 계열 |
| 5 | RS | 37 | Rim Shot / Side Stick |
| 6 | CH | 42, 44 | Closed Hi-Hat / Pedal Hi-Hat |
| 7 | OH | 46 | Open Hi-Hat |
| 8 | CR | 49, 57 | Crash Cymbal 1/2 |
| 9 | RD | 51, 59 | Ride Cymbal 1/2 |
| 10 | BL | 53, 56 | Bell 계열 (Ride Bell, Cowbell 포함) |
| 11 | CP | 39 | Hand Clap |
하위 디렉토리(00_orig_MIDI_files)에 있는 모든 .MID 파일에 대하여 이 스크립트를 실행하고 화면 출력을 하나의 텍스트 파일에 담는 명령어는 다음을 참고하라. 생성된 패턴 MID 파일에 대해서는 재작업을 하지 않아야 하니 명령어가 한층 더 복잡해졌다. Bash가 그립다! 이전 단계에서 동일한 장르의 패턴이 만들어진 경우 기본 동작은 덮어쓰기이므로, 이를 방지하려면 '--no-overwrite' 옵션을 주어야 한다.
$log = "all_results.txt"
Remove-Item $log -ErrorAction SilentlyContinue
Get-ChildItem ".\00_orig_MIDI_files" -Filter *.mid |
Where-Object { $_.Name -notmatch '_P\d{3}\.mid$' } |
ForEach-Object {
Write-Host "Processing $($_.Name)..."
"===== FILE: $($_.Name) =====" | Out-File -FilePath $log -Append -Encoding utf8
python .\tools\split_drums_2bar_save.py $_.FullName --no-overwrite --export-grid --similarity 80 `
2>&1 | Out-File -FilePath $log -Append -Encoding utf8
"" | Out-File -FilePath $log -Append -Encoding utf8
}
Processing 12bar1.mid...
Processing 12bar4.mid...
Processing 12bar6.mid...
Processing 12bar7.mid...
Processing 2AFROCUB.MID...
Processing 2BALLAD.MID...
Processing 2BLUES.MID...
2-bar .MID 파일로 분할한 뒤 이를 전부 다른 폴더로 옮기려면 다음과 같이 한다. 작업 디렉토리는 work라고 가정한다. work\00_orig_MIDI_files\ABC_P001.MID → work\MID로 전부 옮긴다.
Get-ChildItem "00_orig_MIDI_files" -Filter *.mid |
Where-Object { $_.Name -match '^[A-Za-z]{3}_P[0-9]{3}\.MID$' } |
Move-Item -Destination '.\MID'
> python.exe .\tools\mid2adt.py --in-dir .\MID --out-dir .\ADT
mid2adt.py가 분할된 2-bar 패턴의 straight/triplet 여부를 자동으로 인식한다.
> python.exe .\tools\adt2adp.py --in-dir .\ADT --out-dir .\ADP
> python .\tools\mkindex.py --patterns .\ADP\ --out .\SD\SYSTEM\INDEX.TXT
.\ADP\*.ADP 및 .\SD\SYSTEM\INDEX.TXT를 SD 카드의 \PATTERNS와 \SYSTEM으로 복사하면 된다.
패턴을 많이 모으게 되면 그중에는 틀림없이 똑같은 것도 나타날 것이다. 패턴이 몇개 되지 않는다면 그리드로 시각화하여 눈으로 비교하는 것이 가능하나, 그 숫자가 늘어나면 곤란하다. 2-bar 드럼 연주 MIDI 파일을 서로 비교하여 유사도 매트릭스를 구하는 스크립트인 drum_sim_patrix.py를 만들었다. 자세한 이론은 논문을 써야 할 정도로 심오하니 drum_sim_matrix_manual 문서를 참조하는 것으로 만족하자.