반응형

파이썬, 미디 파일 구조 분석용 코드 예제

글. 오상문 sualchi@daum.net

 

미디 파일을 열어서 저장 포맷을 확인하는 파이썬 코드입니다. 

표준 미디 파일 구조에 대한 내용은 아래 링크를 참조하세요,

blog.daum.net/sualchi/13720994?category=2090044

 

표준 미디 파일 구조(포맷, 형식)

표준 미디 파일 구조 글. 오상문 sualchi@daum.net 표준 미디 파일(SMF)은 데이터 블록, 즉 청크(chunk) 단위로 이루어져 있습니다. 앞에 헤더 청크가 나오고 뒤에 한 개 이상의 트랙 청크가 나타납니다. S

blog.daum.net

# 미디 파일 구조 분석 프로그램 v0.2
# 미디 파일의 헤더 청크와 첫 데이터 청크 정보를 검사함
# 2021.02.09
# by 오상문 sualchi@daum.net
filename = r"c:\temp\test.mid"  # MIDI Filename
try:
    with open(filename, 'rb') as f:
        data = f.read()
except:    
    print("파일 오픈 에러...")
    exit(1)
print("="*60)
print("파일 이름:", filename)
print("="*60)
try:
    cType = data[:4].decode()
except:
    print("DecodeError 또는 미디 파일 아님")
    exit(1)
if cType == "MThd":
    print("청크 종류: 헤더", cType)
else:
    print("미디 파일 아님")
    exit()
# print(data[:4])
size = data[7]
print("다음 데이터 길이:", size, "Bytes")
# print(data[4:8])
trackType = data[9]
if trackType == 0:
    print("트랙 유형: 단일 트랙")
elif trackType == 1:
    print("트랙 유형: 1개 이상 트랙, 동시 진행")    
elif trackType == 2:
    print("트랙 유형: 1개 이상 트랙, 순차 진행")    
else:
    print("트랙 유형: 모름")    
# print(data[8:10])
trackCnt = data[11]
print("트랙 수:", trackCnt)
# print(data[10:12])
if data[12] & 0b10000000 == 1:
    print("초당 SMTPE 프레임 수:", data[12] & 0b01111111)
    print("SMTPE 프레임당 틱 수:", data[13])
else:
    unitTime = data[12]*0xff + data[13]   # 12, 13
    print("단위시간 수:", unitTime, "(4분음표 길이(틱수))")
#print(data[12:14])
print("-"*60)
partList = data.split(b"MTrk")
print("MTrk 데이터 파트 개수:", len(partList)-1)  # MTrk 파티 개수 
for i in range(len(partList)):
    print(i,":", len(partList[i]), "Bytes")
'''
start = 14
cnt = 0
while cnt < trackCnt:
    pos = data[start:].index(b"MTrk")
    start += pos
    print(data[start:start+4].decode(), start)
    start += 4
    cnt+=1
'''
cType = data[14:18].decode()
if cType == "MThd":
    print("청크 종류: 헤더", cType)
elif cType == "MTrk":
    print("청크 종류: 데이터", cType)
else:
    print("청크 종류: 모름", cType)
# print(data[14:18])
size = data[18]*0xffffff + data[19]*0xffff + data[20]*0xff + data[21]
print("다음 데이터 길이:", size, "Bytes")
#print(data[18:22])
print("데이터:", data[22: 22+size])
print("-"*60)

 

테스트용 미디 파일

test.mid
0.01MB

[실행 결과]

============================================================
파일 이름: c:\temp\test.mid
============================================================
청크 종류: 헤더 MThd
다음 데이터 길이: 6 Bytes
트랙 유형: 1개 이상 트랙, 동시 진행
트랙 수: 4
단위시간 수: 120 (== 4분음표시간/단위시간개수)
------------------------------------------------------------
청크 종류: 데이터 MTrk
다음 데이터 길이: 116 Bytes
데이터: b'\x00\xffX\x04\x02\x02\x18\x08\x00\xffY\x02\xfd\x00\x00\xffQ\x03\x08\xb8$\x82
\x89+\xffQ\x03\t\'\xc0\x81m\xffQ\x03\t\x89hx\xffQ\x03\t\xf3\x8d\x82k\xffQ\x03\x08\xb8$
\xd4)\xffQ\x03\t?l\x81t\xffQ\x03\t\xbdYx\xffQ\x03\n\xc5ZB\xffQ\x03\rv\xb0\x811\xffQ\x03
\r\xdf"\x07\xffQ\x03\x10\xa5]\x10\xffQ\x03\x13\x12\xd0\n\xffQ\x03\x16\xe3`\x00\xff/\x00'
------------------------------------------------------------

이상.

 

[참고] 표준 미디 파일 형식 

 

SMF = <header_chunk> + <track_chunk> [+ <track_chunk> ...]


Header Chunk

      The header chunk consists of a literal string denoting the header, a length indicator, the format of the MIDI file, the number of tracks in the file, and a timing value specifying delta time units. Numbers larger than one byte are placed most significant byte first. header_chunk = "MThd" + <header_length> + <format> + <n> + <division>

"MThd" 

      4 bytesthe literal string MThd, or in hexadecimal notation: 0x4d546864. These four characters at the start of the MIDI file indicate that this

 

      is

 

      a MIDI file.

<header_length> 

      4 byteslength of the header chunk (always 6 bytes long&emdash;the size of the next three fields).

<format> 

      2 bytes

0 = single track file format

1 = multiple track file format

2 = multiple song file format

<n> 

      2 bytesnumber of tracks that follow

<division> 

    2 bytesunit of time for delta timing. If the value is positive, then it represents the units per beat. For example, +96 would mean 96 ticks per beat. If the value is negative, delta times are in SMPTE compatible units.

Track Chunk

      A track chunk consists of a literal identifier string, a length indicator specifying the size of the track, and actual event data making up the track. track_chunk = "MTrk" + <length> + <track_event> [+ <track_event> ...]

"MTrk" 

      4 bytesthe literal string MTrk. This marks the beginning of a track.

<length> 

      4 bytesthe number of bytes in the track chunk following this number.

<track_event>

      a sequenced track event.

Track Event

      A track event consists of a delta time since the last event, and one of three types of events. track_event = <v_time> + <midi_event> | <meta_event> | <sysex_event>

<v_time>

      a variable length value specifying the elapsed time (delta time) from the previous event to this event.

<midi_event>

      any MIDI channel message such as note-on or note-off. Running status is used in the same manner as it is used between MIDI devices.

<meta_event>

      an SMF meta event.

<sysex_event>

      an SMF system exclusive event.

Meta Event

      Meta events are non-MIDI data of various sorts consisting of a fixed prefix, type indicator, a length field, and actual event data.. meta_event = 0xFF + <meta_type> + <v_length> + <event_data_bytes>

<meta_type> 

      1 bytemeta event types:
Type Event Type Event
0x00 Sequence number 0x20 MIDI channel prefix assignment
0x01 Text event 0x2F End of track
0x02 Copyright notice 0x51 Tempo setting
0x03 Sequence or track name 0x54 SMPTE offset
0x04 Instrument name 0x58 Time signature
0x05 Lyric text 0x59 Key signature
0x06 Marker text 0x7F Sequencer specific event
0x07 Cue point

<v_length>

      length of meta event data expressed as a variable length value.

<event_data_bytes>

      the actual event data.

System Exclusive Event

      A system exclusive event can take one of two forms:

sysex_event = 0xF0 + <data_bytes> 0xF7 or sysex_event = 0xF7 + <data_bytes> 0xF7

In the first case, the resultant MIDI data stream would include the 0xF0. In the second case the 0xF0 is omitted.


Variable Length Values

Several different values in SMF events are expressed as variable length quantities (e.g. delta time values). A variable length value uses a minimum number of bytes to hold the value, and in most circumstances this leads to some degree of data compresssion.

A variable length value uses the low order 7 bits of a byte to represent the value or part of the value. The high order bit is an "escape" or "continuation" bit. All but the last byte of a variable length value have the high order bit set. The last byte has the high order bit cleared. The bytes always appear most significant byte first.

Here are some examples:

Variable length Real value 0x7F 127 (0x7F) 0x81 0x7F 255 (0xFF) 0x82 0x80 0x00 32768 (0x8000)

 

 

대치동, 잠실 코딩 교육 문의: 010-4440-0813 (오상문 원장)

반응형

+ Recent posts