2022년 9월 12일 월요일

python으로 mid file 분석, chunk

0. mid

mid 파일은 일반적인 음악을 재생하기 위한 format입니다. 

보통 음악이라고 하면 mp3나 ogg를 생각 할 수도 있는데 해당 종류의 음악 파일은 wav->mp3, ogg로 변환되어 있는 소리의 시간 샘플링이 파일이 됩니다. 압축 파일을 어떠한 형태로 하느냐에 따라 여러가지 포맷으로 나뉘게 되며 기본적으로는 wave 파일이 기본이 됩니다.

mid 파일의 기본은 피아노 건반의 이벤트를 기록한 파일이라고 생각하면 됩니다. 따라서 wave파일 형태 보다는 용량의 크기가 굉장히 작습니다. 좀 더 쉽게 말하자면 '도레미파솔라시도' 같은 음표를 저장하고 있는 형태라고 생각하면 됩니다.

갑자기 mid 파일을 분석을 시작했냐고 한다면, Machine Learning 작곡 쪽에 관심이 생겨서 살펴보다 보니 이 부분의 정리가 필요하다고 판단이 되었습니다.


mid file spec은 로그인 해야지만 볼 수 있어서 여기에서 사용한 주된 코드는 아래 링크로부터 참고 하였습니다.

https://github.com/mido/mido : python의 mid파일을 읽어오고 재생하는 패키지

http://www.ccarh.org/courses/253/assignment/midifile/ : mid 샘플 분석 자료

https://faydoc.tripod.com/formats/mid.htm : mid 파일 구조


1. chunk 의 이해

많은 종류의 file format에서 일반적으로 사용하는 chunk라는 개념이 있습니다. chunk는 PNG, IFF, MP3 및 AVI와 같은 많은 멀티미디어 파일 형식에서 사용되는 정보의 조각이며, chunk를 사용하는 이유 중의 하나라면 format의 확장성 및 길이의 가변 처리 때문에 많이 사용합니다.

mid 파일도 chunk를 사용하는데 아래와 같은 format을 가집니다.

MThd, MTrk String을 가지는 대표적인 chunk가 있습니다. 더 많은 chunk가 있을 듯 하지만 full spec을 보지 못한 상태이고 많은 곳에서 두개의 트랙만을 이용해서 설명하고 있어서 여기에서도 두개의 chunk분석을 할 예정입니다.


2. chunk 분석

파일을 읽는건 여기에서는 numpy로 한번에 fromfile로 읽었습니다. 보통 mid파일이 크지 않기 때문에 큰 문제는 없습니다. 

numpy로 읽은 데이터는 slice가 가능하기 때문에 실제 코드에서는 다음과 같은 형태를 사용하였습니다. bdata[read_pos:read_pos+4]

그리고 read_pos는 현재 읽는 위치를 의미합니다. 해당 값을 증가시켜 가면서 처리를 해주면 됩니다.

길이를 읽을 때는 4 byte 데이터가 big 엔디언으로 되어있어서 int.from_bytes를 이용해서 변환해서 읽어 주었습니다.

여기에서 사용한 샘플 mid는 엘리제를 위하여 mid 파일입니다.


전체 소스

import numpy as np

filename = "../00_data/tests_for-elise.mid"

with open(filename) as f:
    rectype = np.dtype(np.byte)
    bdata = np.fromfile(f, dtype=rectype)

print(bdata)

# MID 파일은 chunk의 연속으로 되어 있습니다.
# Chunk Type(4), chunk body length (4), body(chunk body length)
read_pos = 0
while True:
    chunk_type = bdata[read_pos:read_pos+4].tobytes()
    chunk_type = chunk_type.decode('utf-8')
    chunk_length = int.from_bytes(bdata[read_pos+4:read_pos+8].tobytes(), 'big')

    print(chunk_type, chunk_length)

    read_pos = read_pos + chunk_length + 8
    if len(bdata) <= read_pos:
        break


실행결과

[ 77  84 104 ...  -1  47   0]
MThd 6
MTrk 3909
MTrk 3034


관련 소스

sourcecode/music/01_mid at main · donarts/sourcecode · GitHub


다음에는 MThd, MTrk chunk를 분석해보도록 하겠습니다.


MThd : https://swlock.blogspot.com/2022/09/python-mid-file-mthd.html

MTrk : https://swlock.blogspot.com/2022/09/python-mid-file-mtrk.html



댓글 없음:

댓글 쓰기