야, 너도 드럼 칠 수 있어 : 1. 드럼 비트 샘플 파일 입력
드럼 악보 채보 프로젝트
- 본 글은 제 대학교 3학년 여름 방학이었던 2019년 6월부터 3개월 간 진행했던, “야, 너도 드럼 칠 수 있어” 프로젝트에 관련된 설명 글입니다.
- 편의상 설명 과정은 ‘~했다.’ 로 작성하였습니다.
- 소스 코드 는 다음과 같습니다. (Source)
채보의 사전적 정의 : 음악을 듣고 악보로 옮겨 적는 것
이전 글 “(야, 너도 드럼 칠 수 있어 : 0. 개요)” 에서 이어지는 글입니다.
0. 사용 라이브러리
- 먼저, import 항목들은 다음과 같다.
1 2 3 4 5 6 7 8 | import numpy as np import matplotlib.pyplot as plt import scipy.io.wavfile as wav import wave import glob import os.path import cv2 import sounddevice as sd | cs |
- 주요 라이브러리와 사용된 이유는 아래와 같다.
1. numpy
- 배열을 생성, 편집할 수 있는 라이브러리. FFT 메소드가 내장되어 있어 이를 활용하기 위해 사용.
2. matplotlib
- 그래프를 plot하기 위한 라이브러리. 개발 과정 중 여러 실험들을 진행하며, 직접 결과를 확인하기 위해 사용.
3. scipy, wave
- scipy는 여러 과학적 계산과정이 포함된 라이브러리이며, wave와 함께 .wav 파일을 분석하기 위해 사용.
4. glob, os.path, cv2
- 모두 파일 입,출력을 구현하기 위해 사용.
5. sounddevice
- 결과 시연 과정에서 파일을 재생하는 과정에 사용.
1. 파일 입력과 경우의 수 분류
- 먼저, “.wav”파일을 불러오기 위해 다음과 같이 추가했다.
1 2 | myPath = 'PATH' myExt = '*.wav' | cs |
PATH에 주소를 지정하고, “.wav”확장자를 불러온다.
- 이후, (후에 사용될) 이미지 파일을 불러왔다.
1 | default = cv2.imread("C:/drum/default.png",cv2.IMREAD_REDUCED_COLOR_4) | cs |
드럼을 총 여섯 가지의 구성 요소로,
Kick, Snare, Tom, Ride, Crash, Hi-Hat 으로 분류했다.
(low/mid/high Tom, closed/open Hi-Hat은 따로 분류하지 않았다.)
드럼을 연주할 때, 한 번에 최대로 연주될 수 있는 요소는 셋 이라고 판단했다.
(양손에 채 하나, 킥 드럼 하나)
따라서 다음과 같이 각 경우의 수를 상세하게 생각했다.
1. 동시에 한 가지의 악기 연주
# | 연주 방법 | 연주하는 악기 |
---|---|---|
1 | 한 손 | Crash |
2 | 한 손 | Ride |
3 | 한 손 | Hi-Hat |
4 | 한 손 | Tom |
5 | 한 손 | Snare |
6 | 발 | Kick |
Kick만 발 로 연주하는 것을 알 수 있다. (손으로 Kick을 연주하는 사람은 제외)
2. 동시에 두 가지의 악기 연주
# | 연주 방법 | 연주하는 악기 |
---|---|---|
1 | 두 손 | Crash, Ride |
2 | 두 손 | Hi-Hat, Crash |
3 | 두 손 | Hi-Hat, Ride |
4 | 발, 한 손 | Kick, Crash |
5 | 발, 한 손 | Kick, Hi-Hat |
6 | 발, 한 손 | Kick, Ride |
7 | 양 손 | Snare, Crash |
8 | 양 손 | Snare, Hi-Hat |
9 | 한 손, 발 | Snare, Kick |
10 | 양 손 | Snare, Ride |
11 | 양 손 | Snare, Tom |
12 | 양 손 | Tom, Crash |
13 | 양 손 | Tom, Hi-Hat |
14 | 한 손, 발 | Tom, Kick |
15 | 양 손 | Tom, Ride |
Kick이 포함된 5가지 경우의 수와, 다른 5가지 악기의 경우의 수이다.
3. 동시에 세 가지의 악기 연주
# | 연주 방법 | 연주하는 악기 |
---|---|---|
1 | 발, 양 손 | Kick, Crash, Ride |
2 | 발, 양 손 | Kick, Hi-Hat, Crash |
3 | 발, 양 손 | Kick, Hi-Hat, Ride |
4 | 발, 양 손 | Kick, Snare, Crash |
5 | 발, 양 손 | Kick, Snare, Hi-Hat |
6 | 발, 양 손 | Kick, Snare, Ride |
7 | 발, 양 손 | Kick, Snare, Tom |
8 | 발, 양 손 | Kick, Tom, Crash |
9 | 발, 양 손 | Kick, Tom, Hi-Hat |
10 | 발, 양 손 | Kick, Tom, Ride |
Kick이 무조건 포함되므로, 경우의 수는 10가지이다.
마지막으로, 아무것도 연주하지 않은 초기 상태를 default로 두었다.
그렇게 총 32 개의 이미지를 준비했다.
2. 샘플링레이트와 진폭 계산
- 이후, 입력된 파일들을 분석했다.
1 2 3 4 5 6 7 8 9 10 | for filename in glob.glob(os.path.join(myPath, myExt)): rate, data0 = wav.read(filename) data1 = np.full(np.alen(data0), 0) data2 = np.full(np.alen(data0), 0) data1 = np.array(data0) times = np.arange(len(data0)) / float(rate) original = wave.open(filename, 'rb') nChannel = original.getnchannels() length = original.getnframes() original.close() | cs |
- glob과 os.path를 활용해 입력, 출력 부분을 설정했다.
- data* 이름으로 변수를 설정했다.
- 총 프레임을 시간으로 나누어 Sampling-rate를 구했다.
- wave를 활용해 파일의 채널과 총 길이를 구했다.
만약 입력이 Stereo일 경우
- Stereo 일 경우 wave 라이브러리로 처리하기 어려워, 간단히 Left 채널 만을 사용했다.
1 2 3 | if nChannel == 2: data2 = data0[:, 0] data1 = data2 | cs |
nChannel = 2일 경우 data0[:, 0] 를 대입해 Left 채널만 활용했다.
이같은 과정을 통해 샘플 파일을 입력했고, 기초적인 값들의 계산과 변수 선언을 마쳤다.
이제 FFT 등 실질적으로 신호를 처리하는 메소드를 구현할 차례이다.
다음 글 “(야, 너도 드럼 칠 수 있어 : 2. 처리 과정 구현)” 에서 이어집니다.
댓글남기기