Python居然還能創造音樂~果然是無所不能的語言啊!

前言

上期留了尾,賣了關子。接著上回用 Python 播放多聲軌 MIDI 文件音樂繼續為您說。

如今,許多人嘗試用計算機創作樂器,普遍方法是隨機生成一段音樂,和現有曲子的相似度進行打分,一個分值範圍內算通過。我也這麼做?不,這樣做效率低下,隨機生成幾千首隻有一首通過,計算速度也十分低下(超級電腦不說),篩選出的曲子也不一定好聽。

我用什麼方法呢?今天,我們要了解許多令人髮指的樂理,以及計算令人髮指的樂理公式。準備好筆紙了麼?今天,就讓我,帶您進入美妙複雜的音樂殿堂吧!

樂理的代碼:

廢話不多說,先來講講“音程”:

音程及其算法:

看著玄乎,其實是最簡單,它表示兩音之間的“距離其基本單位稱為度。在mido中,

以“半音”為基本單位,接下來,我都採用半音計數

1:小二度2:大二度/減三度3:小三度/增二度4:大三度/減四度5:純四度/增三度6:增四度/減五度7:純五度/減六度8:小六度/增五度9:大六度/減七度10:小七度/增六度11:大七度單位:半音

除了四度和五度(八度不算)度按減小大增來計算沒有基準

。但,一般“大度”為最佳選擇。不信可以嘗試下,是大三度好聽,還是小三度好聽。除四度以外,只有理論上的增減,不會說增三度,只說純四度。因此,只需做11個函數就行了。比如說小二度:

<code>1.def sd_two(low=None,high=None):         #小二度  
2.    if type(low) == str:  
3.     ···#就是轉換,前面的代碼都寫過  
4.    yin = []  
5.    if low and high == None:  
6.        high = low + 1  
7.    if high and low == None:  
8.        low = high - 1  
9.     yin.append(low)  
10.    yin.append(high)  
11.    return yin  /<code>

我花了整天肝枯燥的做簡單計算 的代碼,想看去我的Github:

https://github.com/duoduo666/mido-Barock/blob/master/turn%20note/yin_cheng.py

記得star哦。

三和絃:

三和絃有四類,大三和絃,小三和絃,增三和絃,減三和絃。七和絃較複雜,有興趣讀者可自己搜搜。

大三和絃結構是:大三度+小三度。小三和絃結構是:小三度+大三度。增三和絃結構是:大三度+大三度,減三和絃結構是:小三度+小三度。最舒服的和絃是大三和絃,最噁心的和絃是減三和絃。

因此,我們只要知道一個音,就可以求出其他的音。我在這貼大三和絃代碼:

<code>1.def b_three(geng=None,zhong=None,wu=None):  
2.        yin = []  
3.        if geng and zhong == None and wu == None:    #知道根音  
4.            zhong = geng + 4  
5.            wu = zhong + 3  
6.             yin.append(geng)
7.             yin.append(zhong)
8.             yin.append(wu)
9.             return yin
10.        if zhong and geng == None and wu == None:      #知道中音  
11.            geng = zhong - 4  
12.            wu = zhong + 3  
13.             ····#同上
14.        if wu and geng == None and zhong == None:      #知道五音  
15.            zhong = wu - 3  
16.            geng = zhong - 4  
17.            ····#同上/<code>

轉位

三和絃有四類,每類都有3種“形態”,稱為“轉位”,分別是:

第一轉位(原位),第二轉位(4轉位),第三轉位(46轉位)

每次轉位把最低音(根音)提八度(12半音)。為大家理解,我畫了大三和絃轉位圖(單位:半音)。

Python居然還能創造音樂~果然是無所不能的語言啊!

X代表根音(最低音),Y代表三音(中間音),Z代表五音(最高音)。清楚多了吧,其餘三個皆如此。

腦筋都不用動了,直接出轉換代碼。(轉換位大4和絃)

<code>·····  #前面有
2.    yin = []  
3.    if geng and zhong and wu:                        #若是三個都有  
4.        if zhong - geng == 4 and wu - zhong == 3:    #若是第一轉為(三和絃)  
5.            geng += 12  
6.            yin.append(zhong)  
7.            yin.append(wu)  
8.            yin.append(geng)  
9.            return yin  
10.        if zhong - geng == 5 and wu - zhong == 4:    #若是第三轉為(46和絃)  
11.            wu -= 12  
12.            yin.append(wu)  
13.            yin.append(geng)  
14.            yin.append(zhong)  
15.            return yin  
16.         if zhong - geng == 3 and wu - zhong == 5:  
17.            return True  /<code>

但是,種類太多我花了10天誇張) 完成,這不貼了,有興趣的到我的GitHub

https://github.com/duoduo666/mido-Barock/tree/master/turn%20note

配上和絃(音程):

哇!可以求和絃和、音程了!鼓掌!。動動腦筋,在myin基礎上,更改下,給曲子配上和絃:

<code>1.    def myin(fu,pai,time=120,du=None,chord=None,high=64,note="low",yue=2):  
2.        #和聲版  
3.        pig = int(beat(time))    #int取整,time要求整數
4.        for i in range(len(pai)):  
5.            if type(pai[i]) == list:  
6.                ···   #上篇文章有,看看
7.            else:
8.                if chord == None and du == None:
9.                    ···  #上篇文章有,看看
10.                else:  
11.                    #和絃  
12.                    if chord == "dasan":            #大三和絃  
13.                        if note == "low":  
14.                            fu[i] = b_three(fu[i])  
15.                        elif note == "zhong":  
16.                            fu[i] = b_three(zhong=fu[i])  
17.                        elif note == "wu":  
18.                            fu[i] = b_three(wu=fu[i])  
19.                    ····· #此處省略一千行  
20.    
21.                    #音程(度)
22.                    if du == "xiaoer":                   #小二度  
23.                        if note == "low":  
24.                            fu[i] = sd_two(fu[i])  
25.                        if note == "high":  
26.                            fu[i] = sd_two(high=fu[i])  
27.                    ····#此處省略一千行  
28.    
29.                    #循環  
30.                    for x in range(len(fu[i])):  
31.                        yin(fu[i][x],pai[i]*pig,liang=high,unit=tra[x],qi=yue)  /<code>

有太多的“音程”、“和絃”,這不可能全貼,看完整代碼?去:

https://github.com/duoduo666/mido-Barock/blob/master/play%20note/play%20note(basic).py

慶祝一下,我用這函數,給《瑪麗有隻小山羊》配了和絃和音程,只有你沒想到,沒有我做不出,去這裡(https://github.com/duoduo666/mido-Barock/tree/master/mary)聽聽。

巴洛克曲子算法及實現:

巴洛克時期有許多不同的種類曲子,二部曲,三部曲,四部曲,賓格,賦格……數不過來,不同種類的曲子有不同形式。今天我們實現二部曲。二部曲有很多形式,單開式,雙起式,加厚式……我們挑個簡單的,“單開式”。

《巴赫二部創意曲》第一首就是講這個。講之前,要貼幾段代碼:

倒影:

打個比方:[3,4,5]的倒影就是[3,2,1]。這形式在巴洛克時期全都是,實現函數:

<code>def dao(yin):                 #計算倒影
    a = yin[0] * 2
    daoyin = []
    for i in yin:
        b = a - i
        daoyin.append(b)
    return daoyin /<code>

首音乘2,以此減接下來的數,得出數組(list)

倒影難道音高不變了?總要變吧。動動腦經,得出答案:

<code>def getdao(xuanlu,base):
    for i in range(len(xuanlu)):
        if type(xuanlu[i]) == str:
            xuanlu[i] = num(xuanlu[i])
    if type(base) == str:
        base = num(base)
    xuanlu = dao(xuanlu)
    high = base - xuanlu[0]
    for i in range(len(xuanlu)):
        xuanlu[i] += high
    return xuanlu/<code>

以base位基音,得出xuanlu倒影。

分拆和絃、時間:

在巴洛克時期,總會把主題(主旋律)拆開來,分成個主題。但你不知道用戶會輸入怎樣的節奏型。再動動腦筋,就可以把旋律按節拍的不同拆開。

<code>1.    def getlu(first,second,ind):  
2.        s = 0  
3.        c = 0  
4.        for i in range(1,len(second)):  
5.            if second[i] != second[s]:  
6.                c += 1  
7.                if c == ind:  
8.                    return first[s:i]  
9.                else:  
10.                    s = i  
11.        return first[s:]  /<code>

同理,分拆時間:

<code>1.    def gettime(paizi,ind):  
2.        s = 0  

3.        c = 0  
4.        for i in range(1,len(paizi)):  
5.            if paizi[i] != paizi[s]:  
6.                c += 1  
7.                if c == ind:  
8.                    return paizi[s:i]  
9.                else:  
10.                    s = i  
11.        return paizi[s:]  /<code>

這樣你就可以獲取任意一段的代碼和時間了。

計算機計算樂曲實現:

有小白生氣了,算法還不講!別急,算法這不就來了?那最經典的BWV772舉例:

Python居然還能創造音樂~果然是無所不能的語言啊!

此圖版權為作者所有!我們用藍色框匡主題,綠色框匡副題和配旋律。用黃色代表倒影。我們用數學的語言總結下:(我畫的)

Python居然還能創造音樂~果然是無所不能的語言啊!

有個特別的。所有的曲子都要“解決”,“解決”是較複雜,有興趣的可以搜搜。這我自己做了個個性化 解決,大家可以拿來用。

<code>lastyin = [b_three(".do"),b_three(".mi"),b_three(".so"),b_three("do"),b_three("mi"),b_three("so"),'so','mi','do',"do","si"]  
lastpai = [xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0.5,0.5,1.5,5]  
myin(lastyin,lastpai,track=track4)  
myin(["do"],[10],high=120)  /<code>

此解決方法嚴禁抄襲。到這,相信只要智商>100,就可以寫出來。但,許多的小白還是不會寫。為了照顧小白,我原來想在這裡貼,但是實在太長,放不下。請去我的barok文件下載(https://github.com/duoduo666/mido-Barock/tree/master/barok)。

結語

如今,您可以通過計算機計算出巴洛克時期的二部曲的開場事了,只要有個好旋律,就可以出個好曲子。但其他的種類呢?可以買本《巴赫創意曲集》,一共30首曲子,每首曲子都很經典。可以自己挨個分析寫代碼哦。


分享到:


相關文章: