2‑bar 드럼 패턴(MIDI 파일)들 사이의 유사도(similarity)를 계산하고, 두 가지 방법으로 얻은 전체 NxN 유사도 행렬을 화면에 출력하는 스크립트입니다.
- 비교 대상: GM 드럼 채널(CH10, = MIDI 채널 번호 9)의 2‑bar 패턴
- 내부 표현: 12개의 드럼 슬롯 × cols개의 시간 스텝(기본 32)로 이루어진 이진 그리드
- 유사도 지표:
1. **Hamming similarity** (해밍 유사도) 2. **Cosine similarity** (코사인 유사도)
각 유사도 값은 모두 1.0에 가까울수록 더 비슷한 패턴을 의미합니다.
- Python 3.8 이상 권장 - 필수 라이브러리
mido (MIDI 파일 파싱)- 선택 사항
비교할 MIDI 파일들은 모두 2‑bar 드럼 패턴이라고 가정합니다
(예: ''split_drums_2bar_save.py''로 잘라낸 결과물).
설치 예시:
pip install mido
이 스크립트의 핵심 아이디어는 드럼 패턴을 하나의 고정 길이 이진 벡터로 바꾼 뒤, 벡터 간의 거리를 재는 것입니다.
1. 각 MIDI 파일(패턴)을 다음과 같이 변환합니다.
cols개의 균일한 스텝으로 분할 (기본값 32 스텝)
2. 그 결과, 각 패턴은 12 × cols 크기의 이진 그리드(0/1)가 됩니다.
12×cols인 1차원 벡터로 평탄화(flatten)3. 이렇게 얻은 두 벡터를 이용해:
를 계산하고, 모든 파일 쌍에 대해 NxN 행렬을 만듭니다.
GM 드럼 노트 번호(35–81)를 12개의 슬롯으로 묶어서 표현합니다.
슬롯 인덱스와 라벨은 다음과 같습니다.
| 슬롯 | 라벨 | 설명 (대략) |
| 0 | BD | Kick (Bass Drum) |
| 1 | SD | Snare Drum (주로 Acoustic/Electric) |
| 2 | RS | Rim Shot / Side Stick |
| 3 | CP | Hand Clap |
| 4 | CH | Closed Hi‑Hat |
| 5 | PH | Pedal Hi‑Hat |
| 6 | OH | Open Hi‑Hat |
| 7 | LT | Low/Low‑mid toms |
| 8 | HT | Mid/High toms |
| 9 | CR | Crash 계열 cymbal |
| 10 | RD | Ride 계열 cymbal & Bell |
| 11 | PER | Cowbell 및 Latin/FX 퍼커션 묶음 |
예를 들어, 킥(35, 36)은 항상 슬롯 0(BD), 스네어(38, 40)는 슬롯 1(SD)에 매핑됩니다.
python drum_sim_matrix.py PATTERN1.MID PATTERN2.MID PATTERN3.MID ...
- 인자로 넘긴 모든 MIDI 파일에 대해 좌표가 정해진 벡터를 만들고, - Hamming / Cosine 유사도를 각각 계산하여 - 두 개의 NxN 유사도 행렬을 출력합니다.
운영체제/쉘 종류에 따라 와일드카드 동작이 다릅니다.
#### (1) Linux / macOS (bash, zsh 등)
쉘이 직접 *.MID를 확장하므로, 다음처럼 쓰면 됩니다.
python drum_sim_matrix.py RCK_P*.MID
#### (2) Windows PowerShell
PowerShell은 기본적으로 와일드카드를 Python에 그대로 넘기므로, 다음처럼 해도 확장이 되지 않습니다.
python drum_sim_matrix.py RCK_P*.MID # (X) 스크립트 안에서 '*'가 그대로 보임
PowerShell에서는 다음처럼 Get-ChildItem을 이용해 확장할 수 있습니다.
python drum_sim_matrix.py (Get-ChildItem RCK_P*.MID).Name ====== 또는 ====== python drum_sim_matrix.py (gci RCK_P*.MID).Name
#### (3) Windows cmd.exe
고전 명령 프롬프트(cmd.exe)는 와일드카드를 자동으로 확장해 줍니다.
C:\> python drum_sim_matrix.py RCK_P*.MID
python drum_sim_matrix.py RCK_P*.MID --cols 32 # 기본값 32
- cols는 2‑bar 구간을 나누는 시간 슬롯 개수입니다.
- 기본값 32는 한 마디당 16 스텝(2마디 = 32 스텝)을 의미합니다.
- 만약 더 촘촘한 해상도가 필요하면 48, 64 등으로 늘릴 수 있습니다.
12×cols로 늘어나며, 계산 비용도 올라갑니다.각 MIDI 파일에 대해 다음과 같은 순서로 벡터를 만듭니다.
1. MIDI 파일 로드 (mido.MidiFile)
2. Type 0이면 첫 번째 트랙, Type 1이면 모든 트랙을 merge
3. delta time을 절대 시간으로 바꾼 abs_msgs 생성
4. 파일의 첫 시점에서의 박자표 (time signature)를 얻고,
ticks_per_beat × 4
5. 2마디 길이 = 2 × bar_ticks 또는 그보다 짧으면 가능한 범위 내
6. 이 구간을 cols개의 균일한 시간 구간으로 나누고,
7. 해당 구간에서 CH10(채널 9)의 note_on 메시지를 조사하여,
0..cols-1)로 매핑8. 이 12×cols 2차원 배열을 평탄화하여 1차원 벡터로 만듭니다.
Hamming distance는 두 개의 같은 길이의 이진 벡터가 있을 때, 서로 다른 비트의 개수를 세는 거리입니다.
예:
- A = 1 0 1 1 0 - B = 1 1 0 1 0
위 두 벡터를 자리별로 비교하면, 서로 다른 위치는 2개입니다. 따라서 Hamming distance d(A, B) = 2입니다.
일반적으로:
- d(A, B) = 서로 다른 위치의 수
- 가능한 값의 범위: 0 (완전히 동일) ~ N (완전히 반대 패턴)
이 스크립트에서는 보다 직관적인 해석을 위해 유사도(similarity)를 다음과 같이 정의합니다.
- 벡터 길이 N (여기서는 12×cols)
- Hamming distance = d
Hamming similarity = 1 - d / N
- 완전히 동일한 패턴 → d = 0 → similarity = 1.0 - 절반 정도만 다름 → d ≈ N/2 → similarity ≈ 0.5 - 완전히 반대(이론적으로) → d ≈ N → similarity ≈ 0.0
두 드럼 패턴의 각 시간 슬롯/슬롯 위치마다 hit 유무(0/1)을 비교하여, - 같은 위치에서 같은 값을 가지면 “일치” - 다르면 “불일치”로 보고 카운트합니다.
#### 장점
- 구현과 해석이 매우 단순합니다. - 2‑bar 그리드가 이미 준비되어 있는 Ardule 환경과 잘 맞습니다. - 패턴을 구체적으로 어느 위치에서 얼마나 다르게 치는지를 정밀하게 반영합니다.
#### 단점 / 주의점
- 한 스텝 정도의 지연/앞당김도 모두 “불일치”로 취급합니다.
- 약간의 swing, shuffle, humanize 등에 대해 둔감하지 못합니다.
따라서 이 값은 “정확히 같은 grid 위에 올려놓았을 때의 모양이 얼마나 같은가”를 보는 척도로 이해하는 것이 좋습니다.
Cosine similarity는 두 벡터 사이의 각도(angle)를 이용한 유사도입니다.
벡터 v₁, v₂에 대해:
cosine_similarity(v1, v2) = (v1 · v2) / (||v1|| * ||v2||)
여기서,
- v1 · v2는 내적(dot product)
- ||v1||, ||v2||는 각 벡터의 길이(노름)입니다.
값의 범위:
- 이진 벡터의 경우 대체로 0.0 ~ 1.0 사이
- 1.0이면 완전히 같은 방향 (패턴이 매우 유사)
- 0.0이면 서로 전혀 겹치지 않는 방향 (공통된 hit 위치가 거의 없음)
패턴을 0/1 벡터로 두었을 때:
- v1 · v2는 두 패턴에서 모두 1인 위치의 개수입니다.
- ||v1||는 v1에서 1의 개수의 제곱근 (√(hit 수))
- ||v2||도 마찬가지
따라서 코사인 유사도는 공통 hit 수를 각 패턴의 전체 hit 수로 정규화한 값에 가깝게 해석할 수 있습니다.
#### 예시 (개념적)
- 패턴 A: 킥과 스네어를 자주 치는 상대적으로 빽빽한 패턴 - 패턴 B: A와 매우 비슷하지만 몇 개의 hit만 빠져 있는 패턴 - 패턴 C: 킥만 몇 번 치는 드문드문한 패턴
A와 B는 공통 hit가 많고 전체 hit 수도 비슷하므로, Cosine similarity가 매우 높은 값(예: 0.95 이상)이 나오기 쉽습니다.
A와 C는 공통 hit가 적고, 한 쪽은 빽빽하고 다른 쪽은 희박하기 때문에, Cosine similarity는 상대적으로 낮은 값이 나옵니다.
- Hamming은 각 위치별로 동일/다름만 본다 → 작은 오차도 모두 불일치로 들어갑니다. - Cosine은 패턴의 전반적인 hit 분포와 공통된 히트의 비율을 강조합니다.
비슷한 스타일로 인식되기 쉽습니다.
#### 간단 비교
| 항목 | Hamming similarity | Cosine similarity |
| —— | ——————– | ——————- |
| 기본 개념 | 서로 다른 비트 수 | 벡터 사이의 각도 |
| 1.0 의미 | 완전히 동일한 패턴 | 방향이 동일(정규화 관점에서 거의 동일) |
| 민감도 | 위치가 한 칸만 어긋나도 크게 감소 | 전체 패턴의 분포와 공통 hit에 더 민감 |
| 해석 난이도 | 매우 직관적 | 약간 수학적이지만 널리 쓰이는 척도 |
두 척도를 함께 보면서: - Hamming은 정밀한 구조 차이, - Cosine은 전체적인 스타일/밀도 차이를 본다고 이해하면 좋습니다.
스크립트를 실행하면, 예를 들어 패턴 4개를 비교했을 때 다음과 같이 출력됩니다.
================================================================================
Hamming similarity matrix (1.000 = identical)
================================================================================
0 1 2 3
0: 1.000 0.945 0.910 0.850
1: 0.945 1.000 0.900 0.840
2: 0.910 0.900 1.000 0.830
3: 0.850 0.840 0.830 1.000
Index → Filename:
0: RCK_P001.MID
1: RCK_P002.MID
2: RCK_P003.MID
3: RCK_P010.MID
================================================================================
Cosine similarity matrix (1.000 = identical)
================================================================================
0 1 2 3
0: 1.000 0.972 0.960 0.900
1: 0.972 1.000 0.955 0.890
2: 0.960 0.955 1.000 0.885
3: 0.900 0.890 0.885 1.000
Index → Filename:
0: RCK_P001.MID
1: RCK_P002.MID
2: RCK_P003.MID
3: RCK_P010.MID
- 위쪽 행렬: Hamming similarity
- 아래쪽 행렬: Cosine similarity
- 왼쪽의 인덱스(0, 1, 2, 3…)는 아래의 Index → Filename 목록과 매칭됩니다.
- 대각선(각 i,i)은 항상 1.000 (자기 자신과의 유사도)입니다.
- (i,j)와 (j,i)는 동일 값입니다 (대칭 행렬).
- Hamming distance
오류 검출·수정 코드, 정보 이론에서 널리 사용됩니다.
“얼마나 많은 위치에서 다른가?”를 측정하는 용도로 사용합니다.
- Cosine similarity
문서 벡터 간 유사도를 잴 때 가장 널리 쓰이는 척도 중 하나입니다.
“벡터가 가리키는 방향이 얼마나 비슷한가”를 의미합니다.
드럼 패턴 연구/리듬 분석 분야에서도 이 두 가지 계열의 아이디어는 흔히 사용되며, 보다 복잡한 연구에서는 Dynamic Time Warping(DTW), 편집 거리(edit distance), 회전 불변(cyclic/invariant) 거리 등으로 확장되기도 합니다.
현재 스크립트는 고정된 grid 위에서의 단순 비교를 수행합니다. 이후 다음과 같은 확장도 고려할 수 있습니다.
1. 회전 불변(cyclic shift‑invariant) Hamming distance
2. 슬롯 가중치 부여
3. 부분 패턴 비교
4. 결과를 CSV/엑셀로 export
필요하다면 이러한 확장 기능을 추가한 버전도 제작할 수 있습니다.