Table of Contents

drum_sim_matrix.py 사용 설명서

2‑bar 드럼 패턴(MIDI 파일)들 사이의 유사도(similarity)를 계산하고, 두 가지 방법으로 얻은 전체 NxN 유사도 행렬을 화면에 출력하는 스크립트입니다.

- 비교 대상: GM 드럼 채널(CH10, = MIDI 채널 번호 9)의 2‑bar 패턴 - 내부 표현: 12개의 드럼 슬롯 × cols개의 시간 스텝(기본 32)로 이루어진 이진 그리드 - 유사도 지표:

1. **Hamming similarity** (해밍 유사도)
2. **Cosine similarity** (코사인 유사도)

각 유사도 값은 모두 1.0에 가까울수록 더 비슷한 패턴을 의미합니다.


1. 요구 사항 및 실행 환경

- Python 3.8 이상 권장 - 필수 라이브러리

  1. mido (MIDI 파일 파싱)

- 선택 사항

  1. 이 스크립트 자체는 추가적인 외부 라이브러리가 필요 없지만,

비교할 MIDI 파일들은 모두 2‑bar 드럼 패턴이라고 가정합니다

  (예: ''split_drums_2bar_save.py''로 잘라낸 결과물).

설치 예시:

pip install mido

2. 기본 아이디어

이 스크립트의 핵심 아이디어는 드럼 패턴을 하나의 고정 길이 이진 벡터로 바꾼 뒤, 벡터 간의 거리를 재는 것입니다.

1. 각 MIDI 파일(패턴)을 다음과 같이 변환합니다.

  1. 채널 10(CH10, 드럼 채널)의 note_on 이벤트만 사용
  2. 시간 축: 2마디(2 bars) 구간을 cols개의 균일한 스텝으로 분할 (기본값 32 스텝)
  3. 음 높이: GM 드럼 노트를 12개의 슬롯으로 매핑 (킥, 스네어, 하이햇, 탐, 심벌, 퍼커션 등)

2. 그 결과, 각 패턴은 12 × cols 크기의 이진 그리드(0/1)가 됩니다.

  1. 특정 슬롯/스텝에 노트가 하나라도 있으면 1, 없으면 0
  2. 이 2차원 그리드를 길이 12×cols인 1차원 벡터로 평탄화(flatten)

3. 이렇게 얻은 두 벡터를 이용해:

  1. Hamming similarity
  2. Cosine similarity

를 계산하고, 모든 파일 쌍에 대해 NxN 행렬을 만듭니다.


3. 드럼 슬롯 정의 (12‑slot 매핑)

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)에 매핑됩니다.


4. 스크립트 사용법

4.1. 기본 호출 형태

python drum_sim_matrix.py PATTERN1.MID PATTERN2.MID PATTERN3.MID ...

- 인자로 넘긴 모든 MIDI 파일에 대해 좌표가 정해진 벡터를 만들고, - Hamming / Cosine 유사도를 각각 계산하여 - 두 개의 NxN 유사도 행렬을 출력합니다.

4.2. 와일드카드(glob) 사용

운영체제/쉘 종류에 따라 와일드카드 동작이 다릅니다.

#### (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

4.3. 옵션: --cols

python drum_sim_matrix.py RCK_P*.MID --cols 32   # 기본값 32

- cols는 2‑bar 구간을 나누는 시간 슬롯 개수입니다. - 기본값 32는 한 마디당 16 스텝(2마디 = 32 스텝)을 의미합니다. - 만약 더 촘촘한 해상도가 필요하면 48, 64 등으로 늘릴 수 있습니다.

  1. 단, 벡터 길이는 12×cols로 늘어나며, 계산 비용도 올라갑니다.

5. 내부 동작: 벡터 생성 과정

각 MIDI 파일에 대해 다음과 같은 순서로 벡터를 만듭니다.

1. MIDI 파일 로드 (mido.MidiFile) 2. Type 0이면 첫 번째 트랙, Type 1이면 모든 트랙을 merge 3. delta time을 절대 시간으로 바꾼 abs_msgs 생성 4. 파일의 첫 시점에서의 박자표 (time signature)를 얻고,

  1. 예: 4/4 → 한 마디의 tick 수 = ticks_per_beat × 4

5. 2마디 길이 = 2 × bar_ticks 또는 그보다 짧으면 가능한 범위 내 6. 이 구간을 cols개의 균일한 시간 구간으로 나누고, 7. 해당 구간에서 CH10(채널 9)의 note_on 메시지를 조사하여,

  1. 해당 시점의 tick 위치를 적절한 스텝 index(0..cols-1)로 매핑
  2. 노트 번호를 12‑slot 중 하나로 매핑
  3. 해당 슬롯/스텝에 노트가 있음을 표시 → 1

8. 이 12×cols 2차원 배열을 평탄화하여 1차원 벡터로 만듭니다.


6. Hamming similarity (해밍 유사도)

6.1. Hamming distance란?

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 (완전히 반대 패턴)

6.2. Hamming similarity 정의

이 스크립트에서는 보다 직관적인 해석을 위해 유사도(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

6.3. 드럼 패턴에서의 의미

두 드럼 패턴의 각 시간 슬롯/슬롯 위치마다 hit 유무(0/1)을 비교하여, - 같은 위치에서 같은 값을 가지면 “일치” - 다르면 “불일치”로 보고 카운트합니다.

#### 장점

- 구현과 해석이 매우 단순합니다. - 2‑bar 그리드가 이미 준비되어 있는 Ardule 환경과 잘 맞습니다. - 패턴을 구체적으로 어느 위치에서 얼마나 다르게 치는지를 정밀하게 반영합니다.

#### 단점 / 주의점

- 한 스텝 정도의 지연/앞당김도 모두 “불일치”로 취급합니다.

  1. 예: 스네어가 한 칸 오른쪽으로 밀려 있으면, 사실상 비슷한 그루브인데도 Hamming distance는 크게 나옵니다.

- 약간의 swing, shuffle, humanize 등에 대해 둔감하지 못합니다.

따라서 이 값은 “정확히 같은 grid 위에 올려놓았을 때의 모양이 얼마나 같은가”를 보는 척도로 이해하는 것이 좋습니다.

7. Cosine similarity (코사인 유사도)

7.1. 정의

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 위치가 거의 없음)

7.2. 이진 벡터에서의 직관

패턴을 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는 상대적으로 낮은 값이 나옵니다.

7.3. Hamming과의 차이

- Hamming은 각 위치별로 동일/다름만 본다 → 작은 오차도 모두 불일치로 들어갑니다. - Cosine은 패턴의 전반적인 hit 분포공통된 히트의 비율을 강조합니다.

  1. 예: 두 패턴이 모두 킥 8번, 스네어 4번, 하이햇 16번 정도의 밀도로 들어있는 경우,

비슷한 스타일로 인식되기 쉽습니다.

#### 간단 비교

항목 Hamming similarity Cosine similarity
————————–——————-
기본 개념 서로 다른 비트 수 벡터 사이의 각도
1.0 의미 완전히 동일한 패턴 방향이 동일(정규화 관점에서 거의 동일)
민감도 위치가 한 칸만 어긋나도 크게 감소 전체 패턴의 분포와 공통 hit에 더 민감
해석 난이도 매우 직관적 약간 수학적이지만 널리 쓰이는 척도

두 척도를 함께 보면서: - Hamming은 정밀한 구조 차이, - Cosine은 전체적인 스타일/밀도 차이를 본다고 이해하면 좋습니다.


8. 출력 형식 해석

스크립트를 실행하면, 예를 들어 패턴 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)는 동일 값입니다 (대칭 행렬).


9. 이론적인 참고 정보 (간단 레퍼런스)

- Hamming distance

  1. Richard W. Hamming이 1950년대에 정립한 개념으로,

오류 검출·수정 코드, 정보 이론에서 널리 사용됩니다.

  1. 여기서는 오류 코드 대신, 드럼 패턴의 이진 표현에 적용하여

“얼마나 많은 위치에서 다른가?”를 측정하는 용도로 사용합니다.

- Cosine similarity

  1. 정보 검색(Information Retrieval), 자연어 처리(NLP)에서

문서 벡터 간 유사도를 잴 때 가장 널리 쓰이는 척도 중 하나입니다.

  1. 이진 또는 실수 벡터 모두에 사용 가능하며,

“벡터가 가리키는 방향이 얼마나 비슷한가”를 의미합니다.

드럼 패턴 연구/리듬 분석 분야에서도 이 두 가지 계열의 아이디어는 흔히 사용되며, 보다 복잡한 연구에서는 Dynamic Time Warping(DTW), 편집 거리(edit distance), 회전 불변(cyclic/invariant) 거리 등으로 확장되기도 합니다.


10. 확장 아이디어

현재 스크립트는 고정된 grid 위에서의 단순 비교를 수행합니다. 이후 다음과 같은 확장도 고려할 수 있습니다.

1. 회전 불변(cyclic shift‑invariant) Hamming distance

  1. 패턴을 한 스텝씩 회전시키며 최소 Hamming distance를 사용
  2. “시작 위치가 달라서 생기는 차이”를 제거

2. 슬롯 가중치 부여

  1. 예: 킥/스네어 차이는 크게, 심벌·퍼커션 차이는 조금만 반영

3. 부분 패턴 비교

  1. 특정 구간(예: backbeat 스네어 위치, 하이햇 패턴 등)만 따로 비교

4. 결과를 CSV/엑셀로 export

  1. 유사도 행렬을 CSV로 저장하여 다른 도구에서 더 편하게 시각화

필요하다면 이러한 확장 기능을 추가한 버전도 제작할 수 있습니다.