python设计一个函数定义计算并返回n价调和函数_音乐编程语言musicpy教程(第三期) musicpy的基础语法(二)...
這個是我在github上給我的項目musicpy寫的wiki,分為數據結構,基礎語法,實際應用三大部分來為大家講解這門音樂編程語言,主要是想給大家寫一個musicpy的詳細的教程與介紹,目前wiki只寫了一部分,不過已經有非常多的東西了。我在這里把github上我目前寫的musicpy的wiki分成幾期連載。github上我的項目musicpy的wiki的地址:
https://github.com/Rainbow-Dreamer/musicpy/wiki
(注:musicpy是我個人開發的一門基于python實現的內部DSL(領域特定語言),整體是一個python庫,我以python的類的運算符重寫以及其他的magic methods的重寫,將musicpy變成了一門符號化的音樂編程語言,有自己的一套獨特的語法與數據結構,musicpy的作曲代碼看上去和python會長得完全不一樣(不過當然也可以寫成很像2333),以后我會更新一些musicpy的作曲代碼示例,給大家體驗一下musicpy的符號化作曲語法)
正文:
Basic grammar of musicpy Part 2 基礎語法(二)
得到一個和弦的所有音符的音名
首先,如果只是得到一個和弦A的音符的列表,那么只需要
A.notes
即可,得到的是和弦A的音符列表,比如A是一個A小七和弦,那么得到的是
[A5, C6, E6, G6]
如果想要得到和弦A的所有音符的音名的列表,那么就可以使用和弦的其中一個內置函數names,比如
chd('A','m7').names()
就可以得到
['A', 'C', 'E', 'G']
對兩個和弦或者兩個音樂片段進行合并連接(聲部合并,聲部拼接)
和弦類型的內置函數add可以合并兩個和弦(或者兩個音樂片段)。 比如現在有兩個音樂片段(和弦類型本身也可以是音樂片段)A 和 B。
參數mode可以用來選擇合并的模式,
當mode == 'head'的時候,
A.add(B, mode='head')
可以得到合并A和B兩個音樂片段后的新的音樂片段,B的開頭對齊到A的開頭,也就是A和B同時從頭開始進行演奏的音樂片段。
合并的機制是重新計算合并過后的音的間隔,然后把A和B的音符按照計算的間隔,調整好順序進行重新的合并排列。 add函數還有一個參數start,可以用來設定B要從A的什么地方開始進行合并,也就是B的開頭對齊到A的什么地方, 單位為小節,換句話說,就是B延后A開始多少小節開始進行演奏。比如:
A.add(B, mode='head', start=8)
可以得到B從A的第8小節開始演奏的合并過后的音樂片段。
進階寫法:
A & B
A & (B, start)
當mode == 'tail'的時候,
A.add(B, mode='tail')
可以得到音樂片段B追加到音樂片段A之后的新的音樂片段,不過需要注意的是,這個模式是直接把B的音符列表追加到A的音符列表之后, 然后把B的音符間隔列表也追加到A的音符間隔列表之后,如果音樂片段A的最后幾個音符間隔是0的話,那么可能會出現音樂片段B的開始幾個音與A的最后幾個音重疊在一起的情況,如果很確定A的最后幾個音符間隔不是0,那么這個模式可以放心地使用。 等價于
A + B
當mode == 'after'的時候,
A.add(B, mode='after')
可以得到音樂片段B追加到音樂片段A之后的新的音樂片段,與tail模式的區別在于,這個模式會特別計算A與B之間是否需要多一些音符間隔, 以避免tail模式里面某些情況下A的結尾與B的開頭會重疊的情況。所以當不確定A的最后幾個音符間隔是否為0的時候,使用這個模式最好。
進階寫法:
A // B
或者
A | B
對一個和弦內的音符做出修改
之前我已經講過如何通過索引值訪問一個和弦內的音符,比如A[1]就會得到和弦A的第一個音符。 想要對一個和弦內的音符作出修改,比如和弦A是一個C大七和弦,
(原位的形式,C, E, G, B)我們想把和弦A的第二個音(三度音)換成F,也就是把和弦A變成一個maj7sus4和弦,我們可以這樣寫:
A[2] = 'F5'
然后我們再打印一下和弦A,
[C5, F5, G5, B5] with interval [0, 0, 0, 0]
會看到和弦A的第二個音已經從E5變成了F5。 請注意,更改的音符可以是音符類型(note('A', 5)這樣子通過note的初始化函數得到的),也可以是表示音符的字符串, 但是一定要有八度數,不能只有音名,比如'F'這樣子就不能用在這里,必須要有一個八度數,比如'F5'這樣子。
對一個和弦的某些音符進行刪除,或者在某個位置插入新的音符
可以參考python的列表的邏輯,使用
del A[n]
可以刪除和弦A的第n個音,使用
A.pop()
可以去掉和弦A的最后一個音,并且返回的是和弦A的最后一個音,使用
A.insert(i, b)
可以在和弦A的第i個位置插入音符b
A.append(b)
可以往和弦A添加音符b 此外,extend, remove函數和列表的同名內置方法使用邏輯也是一樣的。 當你想去掉和弦A里的一個音時,可以使用'-'號來進行去除,比如
A - 'B5'
如果和弦A中有B5這個音符,則會返回一個新的去掉B5這個音的和弦,如果沒有,則會返回未經修改的和弦A。
往一個和弦加上一個最低音(加一個貝斯音符)
比如現在和弦A是一個G major和弦(G大三和弦),組成音依次為G5, B5, D6, 我們現在想往和弦A的下面加上一個C音當做最低音, 那么可以寫
A.on('C5')
得到的是和弦A加上C5作為最低音的新的和弦, 表示出來是
[C5, G5, B5, D6] with interval [0, 0, 0, 0]
進階寫法:
A / 'C5'
查找和弦內某個音是第幾個音
比如和弦A為一個F大九和弦,根音為F5,原位和弦,想找到'E6'這個音在第幾個音,那么可以寫
A.index('E6')
得到的結果是4,說明音符E在F大九和弦的第4個音。 如果音符不在和弦內,則返回-1, 也可以省略八度數,只寫音名進行查找,返回的是第一個音名相同的音符的位置,比如
A.index('G')
得到的結果是5,說明音符G在F大九和弦的第5個音。
往一個和弦后添加休止符
如果要往和弦A的后面添加n小節的休止符,那么可以使用和弦類的內置函數period,
A.period(n)
表示往和弦A后面添加休止符n小節,得到的是一個新的和弦,內容為和弦A加上n小節的休止符。
進階寫法:
A // n
或者
A | n
和弦名解析結構
trans函數可以直接輸入完整的和弦名進行解析,返回的是對應的和弦。支持原位和弦表示,轉位和弦表示,復合和弦表示等等。 trans函數的第一個參數是和弦名,第二個參數是和弦根音的音高(默認值為4), 第三個參數是duration(音符的長度,默認值為0.25),第四個參數是interval(音符的間隔,默認值為None,返回的和弦interval都為0), 比如
trans('Dmaj7')
可以得到
[D5, F#5, A5, C#6] with interval [0, 0, 0, 0]
trans('F/C')
可以得到
[C5, F5, A5] with interval [0, 0, 0]
trans('C')
可以得到
[C5, E5, G5] with interval [0, 0, 0]
trans('Am/Gm')
可以得到
[G5, A#5, D6, A6, C7, E7] with interval [0, 0, 0, 0, 0, 0]
trans('G/C', 6, 1, 1)
可以得到
[C6, G6, B6, D7] with interval [1, 1, 1, 1]
trans函數的簡寫方法:
C(和弦名, 其他的參數)
C表示的是和弦chord的首字母大寫
對一個和弦進行更高級的操作(變化音,省略音,復合和弦)
比如和弦A是一個C屬七和弦,那么如果想要得到C屬七升九和弦,可以這么寫:
A('#9')
得到的是
[C5, E5, G5, A#5, D#6] with interval [0, 0, 0, 0, 0]
C屬七降九和弦則是
A('b9')
比如B是一個C大九和弦,那么如果想要省略三度音,可以這么寫:
B('omit3')
或者
B('no3')
多個升降音和省略音可以使用英文的逗號分隔開來,比如
A('#5, b9, omit3')
如果和弦A是C屬七和弦,那么得到的是C屬七升五降九和弦省略三度音。
如果要構建復合和弦,只需要用'/'連接兩個和弦即可,除了兩個和弦疊在一起的情況, 還有一個和弦下面外加一個最低音構成的復合和弦,這兩種情況都是使用'/'即可。 比如:
C('Amaj7') / 'D'
得到的是
[D5, A5, C#6, E6, G#6] with interval [0, 0, 0, 0, 0]
也就是Amaj7和弦底下加上D作為最低音。 兩個和弦的復合和弦的情況,比如:
C('A') / C('G')
得到的是
[G5, B5, D6, A5, C#6, E6] with interval [0, 0, 0, 0, 0, 0]
也就是G大三和弦疊在A大三和弦下面構成的復合和弦。
和弦轉位一個音轉位到最高音
比如和弦A是C大三和弦原位C, E, G, 現在想把E轉位到最高音,那么可以寫
A.inversion_highest(2)
也就是把和弦A的第二個音放到最高音,得到的和弦的音為C, G, E 進階寫法:
A / -2
或者
A ^ 2
(A / -n 表示把和弦A的第n個音轉位到最高音)
把一個和弦的所有音都轉位到一個八度以內
比如和弦A有5個音,最高的幾個音分布在比低的幾個音更高的八度,那么
A.inoctave()
會返回一個把和弦A的所有的音都放到同一個八度內的和弦類型,八度數為和弦A的第一個音的八度數。
把一個和弦標準化
把和弦A標準化,可以用standardize函數,
A.standardize()
得到的是和弦A標準化之后的新的和弦。
這里標準化的定義是:
1. 如果和弦內有出現重復的音名(即使在不同的八度),那么只保留音高最低(八度數最小)的音。
2. 把所有的音都限制在兩個八度以內,也就是到最低音的15度之內,如果有的音比最低音高的半音數超過兩個八度,那么就往下減一個八度,直到所有的音都在最低音往上的兩個八度之內。
3. 把所有的音名全部統一成沒有升降號或者只有#號的格式,如果有b號的就轉換成十二平均律里等音高的有#號的音名。
標準化之后的和弦的最低音的音高和標準化之前一樣。返回的是和弦A標準化過后的新的和弦。
把一個和弦按照音高數進行排序
如果一個和弦里的音并不是按照音高從小到大進行排序的,比如和弦A的音符依次是E5, C5, G5,那么可以寫
A.sortchord()
返回的是和弦A的音符的音高按照從低到高排序好的新的和弦。
按照設定的音階得到一個和弦的負面和聲
比如和弦A是C大七和弦,想要得到和弦A關于C大調音階的負面和聲的轉換,那么可以寫:
negative_harmony(scale('C', 'major'), A)
得到的是和弦A的音符關于C大調音階的負面和聲的轉換過后的組成的新的和弦。
negative_harmony函數的其他參數:
get_map_dict,為True的時候,返回的是第一個參數音階的每個音符按照負面和聲映射到的音的字典。
為False的時候,如果不傳入任何和弦類型,那么返回的是傳入的音階類型的負面和聲音階類型,比如
negative_harmony(scale('C', 'major'))
得到的是
scale name: C5 minor scale
scale intervals: [2, 1, 2, 2, 1, 2, 2]
scale notes: [C5, D5, D#5, F5, G5, G#5, A#5, C6]
還有一個參數sort,為True的時候,會把和弦a轉換為負面和聲版本之后,將音符按照音高從低到高排序。默認值為True。
音階類型的基礎語法
按照音程關系或者調式名構建音階
scale類(音階類),這個類可以表示一個特定的音階。
使用這個類可以快速按照音的間隔來構建調式,比如大調的音的排列是全全半全全全半(全代表全音,半代表半音),
那么如果想構建一個C大調音階,就可以寫
scale('C5', interval = [2,2,1,2,2,2,1])
這樣就得到了以C5為根音的C大調音階。
當然,對于大部分知名的調式來說,只需要輸入調式的名稱就行了。比如
scale('C5', 'major')
就可以得到以C5為根音的C大調音階,
scale('C5', 'minor')
得到以C5為根音的C小調音階。
在database.py里面的scaleTypes是所有musicpy自帶的調式,用戶也可以自己定制調式。
轉調的具體實例
比如現在有一個音樂片段p是A大調,現在想轉到A小調,那么就可以寫:
p.modulation(scale('A', 'major'), scale('A', 'minor'))
這樣就把音樂片段p從A大調轉到A小調啦~
關于音階類的幾個重要的內置方法的介紹
按照音階的級數選取對應的和弦
比如C大調的4級三和弦是F,6級三和弦是Am,這時候可以用pickchord_by_degree函數,其中的參數degree1是和弦級數,
num是選取多少個音,step是每一次跨越幾個音階中的音。按照默認值,
scale('C', 'major').pickchord_by_degree(5)
會得到一個G大三和弦。
按照五度圈將一個調式進行轉調
fifth函數可以按照五度圈將當前的調式進行轉調,其中的參數step是順著五度圈移動多少步,如果step大于0,那么就會順時針轉調,如果step小于0則是逆時針轉調。fourth函數同理,只是換成了四度圈。
按照和聲功能選取一個音階的和弦
音階類有內置一組較為完整的調式和弦選取函數。比如現在有一個調式A。那么調式A的主和弦就是
A.tonic_chord()
下屬和弦就是
A.subdom_chord()
屬和弦是
A.dom_chord()
等等。想得到調式內某一級的副屬和弦可以用
A.secondary_dom(degree)
其中degree是級數。
得到一個調式的關系調和平行調
relative_key函數可以得到關系調,比如大調的關系小調或者小調的關系大調。
parallel_key函數可以得到同主音大小調。
對一個音階進行升降調(整體升降或者個別的音的升降)
音符類型,和弦類型的up和down函數以及其進階語法也同樣適用于音階。
對一個音階(調式)名進行解析
toScale函數可以直接輸入一個音階(調式)名進行解析,返回的是輸入的音階(調式)名對應的音階類型,主音的八度數(也是音階所在的八度數)
由第二個參數pitch決定,默認值為4。比如
toScale('C major')
可以得到以C5為主音的大調音階,
toScale('G lydian', 6)
可以得到以G6為主音的lydian音階。
簡寫為
S('C major')
S表示的是音階scale的首字母大寫
按照和弦級數提取和弦進行
使用音階類型的內置函數pattern,可以輸入一串表示和弦級數的字符串或者整數來提取一個調式的和弦進行,比如
S('C major').pattern(6451)
可以得到C大調音階的6,4,5,1進行的和弦的列表,
也可以寫
S('C major').pattern('6451')
pattern函數的其他參數:
interval為和弦進行里每個和弦的音符之間的間隔,默認值為0,也就是每個和弦的音符都是一起彈。
duration為和弦進行里每個和弦的音符的長度,默認值為0.25,也就是音符長度為1個小節。
num為按照級數提取調式內的和弦時,每一個和弦提取幾個音,比如num為3就是提取三和弦, num為4就是提取七和弦等等。
step為提取和弦時每一步跳過多少個音階內的音,默認值為2,也就是每次跳過2個音階內的音(自己算一個音),比如C大調音階的1級自然三和弦C E G,
每一次都是跳過兩個音階內的音,C,跳兩個音到E,再跳兩個音到G。(在這里跳過幾個音就是往前走幾步的意思,每走一步就是走到音階內的下一個音)
進階寫法:
S('C major') % 6451
這里給大家附上幾個musicpy語言的音樂代碼示例
1. 東方主旋律:
play((getchord_by_interval('D#4', [5,7,10,7,5], 1/2, 1/8)*3 + getchord_by_interval('F4', [1,0,-4], 1/2, 1/8)) * 3, 150)
2. a = C('Am7')
play(a.period(1/8)*4 + a.up(2).period(1/8)*4 + chd(a[1].up(3), 'maj7').set(interval=1/8))
演奏出A小七和弦后接休止符半拍4遍,然后B小七和弦后接休止符半拍4遍,然后C大七和弦分解和弦1遍。
(以上這兩個例子都是沒有使用進階寫法的,使用進階寫法可以讓musicpy語言看起來更加緊湊,簡短)
3. a = C('Dmaj7') % (1/4,1/4) | C('Cmaj7') | C('Fadd9',3) | C('D#maj7',4) | (C('Dmaj7',3)/-2) % (5/4,)
b = chord(['F#5','G5','A5','B5','G5'], 1/8,1/8)
play(a & b, 140, instrument=1)
(第3個例子使用了很多進階寫法,代碼看起來緊湊了很多,而且對于兩個和弦類型的連接的進階寫法使用分隔符'|'也可以有類似小節線的感覺,可以增強代碼的可讀性。除此之外,和弦連接的分隔符'|'也可以使用'//'來替代,可以看個人喜好使用)
4. a = (C('Amaj7')/2|0.25)*4 + (C('G#m7')/2|0.25)*4 + (C('Gmaj7')/2|0.25)*4 + (C('F#m7')/2|0.25)*4
play(a + a % (1/4,1/4), 165, instrument=9)
(半音下行大七小七和弦交替)
5. a = C('Bmaj9',3)/[2,3,4,1,5]
b = C('Bmaj9',3)/[2,3,4,1,5,2]
q = a + ~a[2:-1]
q2 = b + ~b[4:-1]
t = (q % (1/8,1/8) + q2 % (1/8,1/8)) * 2
adding = chord(['Bb5','Ab5','Gb5','Ab5']) % (1/2,1/2) * 2
t2 = t & adding
play(t2 + (t2 - 3), 100, instrument=47)
(一段有恐怖氛圍的音樂)
這幾個例子大家都可以直接復制粘貼到代碼編輯器里運行,就可以馬上聽到對應的音樂了。(不要忘記最開始要先from musicpy import *,也就是要記得 先import musicpy這個庫)
(下一期更新musicpy的基礎語法第三部分)
總結
以上是生活随笔為你收集整理的python设计一个函数定义计算并返回n价调和函数_音乐编程语言musicpy教程(第三期) musicpy的基础语法(二)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python实现矢量分级渲染_OpenL
- 下一篇: JS应用DOM入门:DOM的对象属性