天天看點

【Win 10 應用開發】MIDI 音樂合成——樂理篇

針對 MIDI 音樂的 API ,其實在 Win 8.1 的時候就出現。在UWP中采用了新的驅動模式,MIDI 消息傳遞更加高效。

首先得說明的是,UWP 的 MIDI 相關 API 不是針對 MIDI 檔案的,而是針對 MIDI 裝置的,是以它不具備儲存 MIDI 檔案的功能。當然,如果你想把 MIDI 消息存為音頻檔案,完全可以自己一個位元組一個位元組地寫入。MIDI 檔案分為兩個資料塊——頭部和音軌。頭部主要描述音軌類型(單軌或多軌),包含軌道數量,以及計時方式。

MIDI 有兩種方式來描述音符時值:

1、Timing Clock:單個四分音符(正常是每四分音符為一拍)的“脈沖時鐘數”(PPQ),時間機關Tick,一般為24的倍數。

2、幀率。這個跟視訊有點像,比如24幀,30幀等。

計時方式用兩個位元組表示(16位),如果最高位為0,表示用Tick方式來描述,剩下的15位表示Tick值;如果最高位為1,則表示幀率。

比如,如果用Tick方式表示(常用),第16位必須為0,即 0111 1111  1111 1111。

MIDI 檔案除頭部外,剩下部分都是音軌資料。每個音軌由一系列事件組成。事件就是MIDI指令。MIDI 檔案之是以體積小,是因為它不存儲音頻資料,隻存儲指令。比如 Note on 開始播放某個音符,Note off 停止播放某個音符。每個事件都由兩段組成:

<delta time><event data>

Delta time 指事件的時間偏移量,它是相對于前一個事件而言的,當然,如果是軌道中的第一個事件(或者是中繼資料事件),delta time 可以是0。常用的是tick計時方式,比如,檔案頭中指定每個四分音符的時值為96,那麼,假調事件A播放中音1(C),事件B停止播放中音1,如果這個中音1是四分音符,即時值為1拍,兩個事件可這樣排列:

<0><note on 60><96><note off 60>

60中音1的編碼,這個老周後面會說,也就是B事件要在A事件後面,相隔時間為96,1拍。如果是八分音符呢,就是48(半拍)。

<0><note on 60><48><note off 60>

好了,關于 MIDI 檔案的資訊就說到這裡,有興趣的話,你可以到 midi.org 官方網站去檢視相關的規範。老周寫了一個讀寫 MIDI 檔案的通用類,功能還未完尚,僅供參考。下載下傳連結在這裡。

=====================================================

下面咱們說正題。

UWP 中的 MIDI API 是用于與 MIDI 裝置通信的。其實總的來說也就兩種裝置:輸入/輸出。輸入裝置一般來說也就是 MIDI 鍵盤了。這個我們一般人用不上,買一個的話也不便宜,起碼要幾百大洋。輸出裝置可以是專門的MIDI聲霸卡,當然,我們一般的聲霸卡也可以。普通聲霸卡支援MIDI 的通用标準,缺點是音色不太真實。專業聲霸卡再配上軟音源就可以模拟出更多樂器的音色,而且品質也高。軟音源也不便宜,買一套大概也要一千大洋。

本篇咱們先不說 API 怎麼用,很簡單,因為微軟都封裝好了的,直接發送 MIDI 消息就行了,或者從外接的 MIDI 鍵盤中接收 MIDI 消息。但是,前提是你得有一點樂理知識。要求不高,能看懂簡譜的話,就可以了。

簡譜頭部

在簡譜上,标題、副标題這些就不多說了,都能看明白的。在簡譜頭部,我們主要了解三個标記:

1、調号。比如我們看到許多簡譜上會标注 1 = C,意思是中音1的發音是鋼琴鍵盤上的【中央C】鍵(白鍵)。調号不了解也無所謂,其實不影響MIDI程式設計,我們就不需要弄得太複雜了,尤其是大調小調的區分,除非你對音樂有興趣,可以研究研究。反正就是調越高聲音越尖銳,調越低聲音越柔和。是以小調一般很适合民歌。

2、拍号:常用的是 4/4,分子為4,表示每四拍為一小節;分母為4,表示一個四分音符為一拍。這是最常見的。比如這樣:

【Win 10 應用開發】MIDI 音樂合成——樂理篇

前面部分是調号,緊跟着是拍号。

如果是,2/4,表明每兩拍為一小節,四分音符為一拍。

3、節奏(節拍):表示每分鐘多少拍(BPM)。常見的節奏為120。

【Win 10 應用開發】MIDI 音樂合成——樂理篇

表示一分鐘 120 拍,是以,每拍的時長為 0.5 秒。

如果是60,表明一分鐘60拍,即一秒一拍。

【Win 10 應用開發】MIDI 音樂合成——樂理篇

實際上,決定曲子速度的不是拍号,而是節奏。120 的曲子速度自然要比 60 的快。拍号隻是确定每個音符的相對時值,标準是四分音符為1拍,那麼八分音符就是半拍,十六分音符就是1/4拍,三十二分音符就是1/8拍了。總之都是二次方的,而且分的越小時值越短。

前面提到MIDI檔案有 Tick 和幀率兩種計時方式,其實計時方式也不會影響曲子的速度(時長),就好比2分鐘長的視訊,你把幀率從 30 幀改為 15 幀,但視訊長度依然是 2 分鐘,隻是變得不太流暢而已。MIDI 中也一樣,速度是由節拍映射(Tempo map)決定的。不同的是,我們簡譜中用的是 BPM(每分鐘多少拍),而MIDI中用的是微秒,比如,BPM=120,即0.5秒一拍,換算為微秒就是 500000了。

小節

上面咱們提到過,4/4表示每四分音符為一拍,每小節一拍。那小節是啥?在簡譜上,用小節線(豎線)來劃分小節。請看下面例子。

【Win 10 應用開發】MIDI 音樂合成——樂理篇

上面例子中有兩個小節,按照拍号的規定,每小節必須是四拍,第一個3是兩拍,第二個3是兩拍,加起來正好是四拍。是以後面緊跟一條豎線,這根線就是小節線。第二個小節中,中音5是一拍,中音2是一拍,緊接着的中音3、1下面都有一橫線,是八分音符,各半拍,加起來正好一拍;最後的低音6是一拍,合起來也是四拍。

再看一個例子。

【Win 10 應用開發】MIDI 音樂合成——樂理篇

注意看拍号,2/4表示每四分音符為一拍,但每小節是兩拍。比如第一小節,中音1、中音2都是四分音符,各一拍,共兩拍,是以構成一個小節。

音符

我們剛剛在簡譜上看到的1234567,就是音符,當然這是簡譜上的表示法,這種表示法,容易識别。在五線譜中,音符是用“蝌蚪文”來表示的,不容易分别,也不好懂。

順便說說唱名和音名。這兩個東西,很多時候都會搞混。所謂唱名,就是你用嘴巴唱出來的時候發的聲,就是

dol  re  mi  fa  sol  la  xi

對應的音符就是 1 2 3 4 5 6 7。這個應該不難,國小生都懂。

音名就是鋼琴鍵盤上那些字母,與唱名對應的是 C D E F G A B。

中國很多樂器(尤其是吹管類)的基本音域都在 1 2 3 5 6 這幾個音上,那是因為我們古代的定音方式為“宮,商,角,徽,羽”,有的說是“宮,商,角,徴,羽”,對應的大約是1 2 3 5 6,古人是用“三分損益”法計算音階的。是以,許多國樂都沒有 4 這個音(3和4的音程是半音),比如,巴烏就是個典型。 笛子和洞箫雖然有 4 這個音(放開全部音孔,八孔箫要按住半音孔),但發聲相對較弱。其實,像巴烏(葫蘆絲)這些樂器也可以通過接中音5以下的音孔來調節出 4 的音,但也是比較弱的。

十二平均律

音階劃分方式很多,比如中國古代有“五度相生”法,五度指純五度,這個很複雜,老周也說不清楚,不過,我可以總結出一句不太靠譜的話——純五度的總音程為 3.5 個全音(三個全音,一個半音)。

其他的計算方式不多講,因為 MIDI 的音階用的是十二平均律,這是世界普及的,琴鍵上用的也是十二平均律。其實,十二平均律是中國人發明的,在明朝的時候就出現了,隻是當時樂器生産工藝限制,沒有人願意接受這種方式,結果讓西方人搶了頭功。

十二平均律是以每【半音】來劃分的,是以,它可以包含12個音:

1、1#、2、2#、3、4、4#、5、5#、6、6#、7

對應的音名為

C、C#、D、D#、E、F、F#、G、G#、A、A#、B

其中,3和4之間的音程是半音,前一八度的7與後一八度的1之間的音程是半音,其餘為全音,比如1和2之間是全音,是以,在1和2之半加一個 1#,表示在1的基礎上升半音,是以,1# 和 2b 是同一個位置,1升半音就是 1#,2 降半音是 2b。

文字是說不清楚的,看看這個圖你就懂了。

【Win 10 應用開發】MIDI 音樂合成——樂理篇

 不管白鍵還是黑鍵,兩個鍵之間的音程都是半音,你會看到,3 和 4 之間沒有黑鍵,因為 3 和 4 之間的音程就是半音。故 12345 就是所謂的純五度,因為它們的總音程就是 3.5 個全音。

再看一張更大的圖。

【Win 10 應用開發】MIDI 音樂合成——樂理篇

這樣你就看到規律了,一個八度的鍵排序是這樣的:

      黑              黑                       黑              黑                黑                        ……

-------------------------------------------------------------------------------------------------------------------

白            白              白      白             白               白                 白             ……

故而,3和4之間是兩個白鍵,7和1之間是兩個白鍵,因為它們的音程都是半音。

将其替換為十二個音符,就是:

    1#       2#              4#        5#        6#            ……

-------------------------------------------------------------------------------

1         2          3   4          5          6          7       ……

 介紹完音符,咱們還要了解音符的時值,所謂時值,就是音符的相對時間長度。

按照時值不同,可以分為以下幾種:

1、全音符。标準情況下是四拍,表示方法為 X - - -。

2、二分音符。标準情況下是二拍,表示方法 X -。

3、四分音符。一拍,表示方法 X。

4、八分音符。半拍,表示方法 

【Win 10 應用開發】MIDI 音樂合成——樂理篇

5、十六分音符。四分之一拍,表示方式 

【Win 10 應用開發】MIDI 音樂合成——樂理篇

6、三十二分音符。八分之一拍,表示方式 

【Win 10 應用開發】MIDI 音樂合成——樂理篇

……

後面就不再分了,時值太短了,你也唱不出來。

當然,也有比較特殊的,比如,三拍時值的音符,也可以表示為 X - -。

好了,隻要有了上面這些基本知識,就可以開始 MIDI 程式設計了。下一篇老周就說說如何向聲霸卡發送 MIDI 消息。本篇就扯到這兒了。

繼續閱讀