MIDI協(xié)議解析以及C++實現(xiàn)-以Unravel.mid為例
????????最近為了做一個小玩意需要解析MIDI協(xié)議,但在單片機(jī)上用網(wǎng)上給電腦程序?qū)懙膸炜偢杏X會有不可預(yù)知的延遲和性能消耗,所以決定自己寫個MIDI的解析,為此學(xué)習(xí)了很多東西,特此寫下專欄留念
????????聲明一下,像二進(jìn)制、十六進(jìn)制、ASCII碼,什么是字節(jié)的這些東西我默認(rèn)讀者已經(jīng)接觸過了,所以我后面將直接對文件內(nèi)容進(jìn)行解析,沒了解過的可以根據(jù)這幾個關(guān)鍵詞先去搜索了解下
本文以我從一個群里下的A叔改編的unravel.mid為例
下載鏈接:https://wws.lanzouq.com/ic7Z6024y0ta
其他mid文件暫時沒看過,可能不太通用,如有錯誤歡迎在評論區(qū)指出

正式開始解析
首先我們以16進(jìn)制打開unravel.mid文件,內(nèi)容如圖
從右邊可以看到一些能夠直接轉(zhuǎn)為字符的信息,如MThd、MTrk則為一塊區(qū)域的頭

接下來便可以劃分區(qū)域:
文件開頭就是4D54 6864(MThd)直到后面出現(xiàn)的第一個4D54 726B(MTrk)前為一塊區(qū)域
存儲了這個MIDI文件的基本信息
第一個4D54?726B(MTrk)直到后面出現(xiàn)的第一個FF 2F為一塊區(qū)域
存儲了如曲目名稱、四分音符的絕對長度等信息
第二個4D54?726B(MTrk)直到后面出現(xiàn)的第一個FF 2F為一塊區(qū)域
存儲了一個軌道的所有MIDI事件信息
若無多個軌道則文件結(jié)束
所以MIDI主要可以分成以上三塊或者說三種區(qū)域
第一塊區(qū)域:
進(jìn)入MThd后的4個字節(jié)便是后面數(shù)據(jù)的長度信息
這里內(nèi)容為6,所以接下來的6字節(jié)便是它的數(shù)據(jù),內(nèi)容解釋在上面注釋好了,想了解其他內(nèi)容或者更加具體的解釋可以看文末參考文獻(xiàn)的第一個文檔
這里主要提取03C0,用來計算延時時間,后面會提到
第二塊區(qū)域:
MTrk里面則是的具體的MIDI事件,按順序由【延時時間(Delta-time)、事件類型、參數(shù)1、參數(shù)2、......、參數(shù)n】組成,其中Delta-time為一個或多個字節(jié)(這次的文件最高只有兩個字節(jié)),后面的參數(shù)個數(shù)由事件類型決定
第一個MTrk主要都是些關(guān)于這個曲目的信息,所以事件基本由都是FF組成,前面的延時在這沒有意義就放到后面再提了,在程序中可以直接找FF來提取信息
FF的參數(shù)一為信息類型、參數(shù)二為信息長度、再后面就是信息內(nèi)容
從這個MTrk中主要可以提取到以下的信息
FF 01????其他信息
FF 02????版權(quán)信息
FF 03????曲目或音軌名稱
FF 51????一個四分音符的絕對時間長度,用其除以MThd中的基本時間可以得到“一個Delta-time的延時時間”
FF 2F????結(jié)束
第三塊區(qū)域:
到這里就是主要的演奏信息了,主要事件就是0x90(按下)和0x80(松開)
在程序中如果只是鋼琴演奏的話其他事件不去執(zhí)行也不會有太大問題,只需要注意CX、DX和FF的參數(shù)數(shù)量
延時:
上面的注釋里寫好了在程序中如何判斷有幾個字節(jié)需要讀取
讀取了之后,將高位減去0x80然后組合在一起便是Delta-time
然后乘上前面第二塊區(qū)域算好的“一個Delta-time的延時時間”便知道需要延時多少微秒
演奏事件:
0x90為按下,0x80為松開,他們后面跟著兩個參數(shù)分別是音符和力度
如此循環(huán)直到FF 2F就結(jié)束了
這樣整個MIDI協(xié)議大體的內(nèi)容就解析完了,下面放我寫的驗證程序,如果訪問不了Github就直接用網(wǎng)盤鏈接和使用文檔即可
Github鏈接:https://github.com/AndyXFuture/CppMidi_Analysis-Play?
網(wǎng)盤鏈接:https://wws.lanzouq.com/iq15e024vs3e?
使用文檔:https://www.bilibili.com/read/cv15852954

參考文獻(xiàn):
MIDI文件格式解析
https://www.jianshu.com/p/59d74800b43b
MIDI tick與絕對時間的換算
https://wenku.baidu.com/view/9b6871f7f90f76c661371ac4.html
(百度文庫的免費文檔,真的是一股清流啊)