其實(shí)我一直是個(gè)音癡,對(duì)音樂(lè)的了解僅限于網(wǎng)易云曲庫(kù)酵颁,但前段時(shí)間看了本大書(shū)《哥德?tīng)柤的悖I釥枺秃?集異璧之大成》材义,很中二的名字均抽,英文名叫《GEB》嫁赏,啥意思呢其掂?就是這三人的英文名G?del,Escher潦蝇,Bach,的縮寫(xiě)款熬,集異璧取得是GEB的諧音。有趣的是這本書(shū)的封皮攘乒,中間的木塊在墻面上留下了GEB三個(gè)字母贤牛,這也正是作者想表達(dá)的:這三個(gè)人其實(shí)是在用不同的方式表達(dá)同一種本質(zhì)。據(jù)作者說(shuō)這個(gè)木塊是他自己連設(shè)計(jì)帶磨则酝,做了了幾個(gè)月才完成的殉簸。。沽讹。
書(shū)歸正傳般卑,說(shuō)說(shuō)卡農(nóng)(不應(yīng)該是Mathematica么?)爽雄,卡農(nóng)不是一首曲子蝠检,是一種譜曲方式,它在不同的時(shí)間上交疊一串相同的旋律挚瘟,交錯(cuò)的旋律之間還能巧妙地彼此配合叹谁,形成一段新的完整的旋律饲梭。
你第一個(gè)想到的卡農(nóng)--“帕赫貝爾的卡農(nóng)”整首曲子都是由一排旋律交錯(cuò)開(kāi)形成的,巴赫真是個(gè)天才焰檩。
你可以在EVA音樂(lè)會(huì)54分30秒處聽(tīng)到這段旋律憔涉,這個(gè)版本給了我用Mathematica做卡農(nóng)的動(dòng)力。
這個(gè)視頻可以幫你更好的了解卡農(nóng)析苫。轉(zhuǎn)自微博劉大可先生
所以我想监氢,既然旋律是重復(fù)的,那不就可以通過(guò)編程實(shí)現(xiàn)嗎藤违。這可以節(jié)省2/3的工作量浪腐,但事實(shí)證明工作量依然很大,主要是扒譜顿乒,真是無(wú)聊又重復(fù)的工作议街。
我就按照我的思路講
由于每一段旋律都會(huì)重復(fù)三遍,所以只需要把旋律的信息交給mathematic璧榄,用Sound[]和SoundNote[]函數(shù)讓Mathematica演奏出來(lái)特漩。
我們需要把每段旋律進(jìn)入的位置告訴給Mathematica,進(jìn)入的第一段旋律是圖中數(shù)字1那列第一行里的八個(gè)音符骨杂,到了下一拍涂身,第二段旋律進(jìn)入,他們進(jìn)入的位置就是對(duì)應(yīng)的數(shù)字搓蚪。還要告訴Mathematica每段旋律的音符是什么蛤售。
五線譜里的音符從下到上對(duì)應(yīng)音調(diào)C4,D4,E4,F4,G4,A4,B4,C5,D5...但挨個(gè)敲字母太麻煩,我把位置對(duì)應(yīng)成數(shù)字妒潭,再構(gòu)建一個(gè)數(shù)字和字母的關(guān)聯(lián)悴能,把數(shù)字翻譯成字母,這樣只需要輸入數(shù)字就可以了
為什么數(shù)字串不一樣長(zhǎng)漠酿?這是因?yàn)闃?lè)譜中音符持續(xù)的時(shí)間長(zhǎng)短不一樣。旋律2中出現(xiàn)的音符是4分音符谎亩,一共8個(gè)炒嘲,假設(shè)每個(gè)音符持續(xù)時(shí)間一秒,旋律2一共8秒匈庭。旋律3中的音符是八分音符夫凸,音符時(shí)值是4分音符的一半,一共16個(gè)音符嚎花,一共也是8秒寸痢。旋律3相當(dāng)于增加了采樣頻率,聽(tīng)起來(lái)更連貫紊选。
有了每段旋律的信息啼止,接下來(lái)編程處理數(shù)據(jù)道逗。
首先把數(shù)字變成音調(diào)字母,seq是我設(shè)的函數(shù)献烦,代表{3,4,5,5,6,3,2,2}這樣的數(shù)字序列滓窍。得到“yinfu”序列
我們需要用到Table[]函數(shù)把“yinfu”里的音調(diào)字母套進(jìn)SoundNote[],生成一個(gè)SoundNote的序列巩那,然后把這個(gè)序列套在Sound[]里吏夯,就可以發(fā)出連續(xù)的音符了。同時(shí)我們還需要設(shè)置延遲即横,這是一段音符序列噪生,我們需要3段音符序列連在一起,要讓他們的時(shí)間錯(cuò)開(kāi)东囚,下圖中的wait+{...}就是干這個(gè)的跺嗽,他定義的是音符序列在整個(gè)曲子中對(duì)應(yīng)的時(shí)間
因?yàn)椴煌L(zhǎng)度的音符占據(jù)的時(shí)間不同,我們還要設(shè)置4種長(zhǎng)度的音符的延遲時(shí)間
把他們拼在一起后放在Sound[]函數(shù)里就可以聽(tīng)到卡農(nóng)了页藻!
我只扒了18段旋律桨嫁,一共20多個(gè)吧,實(shí)在不想扒了份帐,而且到后來(lái)的譜子很奇怪璃吧,處理起來(lái)很麻煩。
有一點(diǎn)忘了說(shuō)废境,卡農(nóng)有個(gè)基調(diào)畜挨,就是從頭彈到尾的,以下是代碼
viobase[seq_List] :=
Module[{ass, t = 1.2, yinfu, v1, insb}, insb = "Cello";
ass = Association[{-4 -> "A3", -3 -> "B3", -2 -> "C4", -1 -> "D4",
0 -> "E4", 1 -> "F4", 2 -> "G4", 3 -> "A4", 4 -> "B4", 5 -> "C5",
6 -> "D5", 7 -> "E5", 8 -> "F5", 9 -> "G5", 10 -> "A5",
11 -> "B5", 12 -> "C6", 13 -> "D6"}];
yinfu = Replace[seq, ass, 1];
v1 = Table[
Table[SoundNote[Take[yinfu, {n}], 8 t*m + {t*(n - 1), t*n}, insb,
SoundVolume -> 0.3], {n, Length[yinfu]}], {m, 0, 12, 1}];
Return[Flatten[v1]]]
vio[ord_Integer, seq_List] :=
Module[{ass, t, wait, yinfu, v1, v2, v3, tt = 1.2, ins},
If[Length[seq] == 8, t = tt]; If[Length[seq] == 16, t = tt/2];
If[Length[seq] == 32, t = tt/4]; If[Length[seq] == 64, t = tt/8];
wait = 8 tt*ord;
ass = Association[{-6 -> "F3", -5 -> "G3", -4 -> "A3", -3 ->
"B3", -2 -> "C4", -1 -> "D4", 0 -> "E4", 1 -> "F4", 2 -> "G4",
3 -> "A4", 4 -> "B4", 5 -> "C5", 6 -> "D5", 7 -> "E5", 8 -> "F5",
9 -> "G5", 10 -> "A5", 11 -> "B5", 12 -> "C6", 13 -> "D6",
14 -> "E6", 100 -> None}];
yinfu = Replace[seq, ass, 1]; ins = "Violin";
v1 = Table[SoundNote[Take[yinfu, {n}], wait + {t*(n - 1), t*n}, ins
, If[Length[yinfu] == 16, SoundVolume -> 0.5,
If[Length[yinfu] == 64, SoundVolume -> 1,
SoundVolume -> 0.6]]], {n, Length[yinfu]}];
v2 = Table[
SoundNote[Take[yinfu, {n}], 8 t + wait + {t*(n - 1), t*n}, ins,
If[Length[yinfu] == 16, SoundVolume -> 0.5,
If[Length[yinfu] == 64, SoundVolume -> 1,
SoundVolume -> 0.6]]], {n, Length[yinfu]}];
v3 = Table[
SoundNote[Take[yinfu, {n}], 16 t + wait + {t*(n - 1), t*n}, ins,
If[Length[yinfu] == 16, SoundVolume -> 0.5,
If[Length[yinfu] == 64, SoundVolume -> 1,
SoundVolume -> 0.6]]], {n, Length[yinfu]}];
Return[Flatten[{v1, v2, v3}]]]
音符數(shù)據(jù)
viobase0 = viobase[{4, 1, 2, -1, 0, -3, 0, 1}]; vio1 = vio[1, {8, 7, 6, 5, 4, 3, 4, 5}]; vio2 = vio[2, {6, 5, 4, 3, 2, 1, 3, 0}]; vio3 = vio[3, {-1, 1, 3, 2, 1, -1, 1, 0, -1, -3, -1, 3, 2, 4, 3, 2}]; vio4 = vio[4, {1, -1, 0, 5, 6, 8, 10, 4, 5, 2, 3, 1, -1, 6, 6, 5}]; vio5 = vio[ 5, {8, 7, 8, -1, -2, 3, 0, 1, -1, 6, 5, 4, 5, 8, 10, 11, 9, 8, 7, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 2, 1, 0}]; vio6 = vio[ 6, {-1, 0, 1, 2, 3, 0, 3, 2, 1, 4, 3, 2, 3, 2, 1, 0, -1, -3, 4, 5, 6, 5, 4, 3, 2, 1, 0, 4, 3, 4, 3, 2}]; vio7 = vio[7, {1, 7, 6, 8, 11, 10, 11, 12}]; vio8 = vio[8, {13, 6, 5, 5, 100, 4, 6, 6, 6, 6, 6, 6, 6, 9, 7, 10}]; vio9 = vio[ 9, {10, 10, 8, 9, 10, 10, 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, 8, 8, 6, 7, 8, 8, 1, 2, 3, 4, 3, 2, 3, 1, 2, 3, 2, 2, 4, 3, 2, 2, 1, 0, 1, 0, -1, 0, 1, 2, 3, 4, 2, 2, 4, 3, 4, 4, 5, 6, 3, 4, 5, 6, 7, 8, 9, 10}]; vio10 = vio[ 10, {8, 8, 6, 7, 8, 8, 7, 6, 7, 5, 6, 7, 8, 7, 6, 5, 6, 6, 4, 5, 6, 6, -1, 0, 1, 2, 1, 0, 1, 6, 5, 6, 4, 4, 6, 5, 4, 4, 3, 2, 3, 2, 1, 4, 3, 4, 5, 6, 4, 4, 6, 5, 6, 6, 5, 4, 5, 6, 7, 6, 5, 6, 4, 5}]; vio11 = vio[ 11, {6, 100, 5, 100, 4, 100, 6, 100, -1, 100, -1, 100, -1, 100, 0, 100}]; vio12 = vio[ 12, {100, 3, 100, 3, 100, 1, 100, 3, 100, 2, 100, 1, 100, 3, 100, 7}]; vio13 = vio[ 13, {8, 1, 2, 1, 0, 7, 8, 7, 6, 1, -1, 4, 3, -4, -5, -4, -4, -4, 5, 4, 3, -4, -5, -4, -3, 4, 3, 4, 5, -2, -3, -2}]; vio14 = vio[ 14, {-1, 6, 7, 6, 5, -2, -1, -2, -3, 4, 3, 4, 5, -2, 1, 0, -1, 6, 7, 9, 8, 1, 3, 8, 6, 9, 8, 9, 7, 3, 2, 3}]; vio15 = vio[ 15, {1, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3, 2, 2, 2, 6, 6, 6, 6, 6, 6, 6, 4, 4, 3, 3, 7, 5}]; vio16 = vio[ 16, {3, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 10, 10, 10, 10, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, 11, 11, 12, 5, 5, 5}]; vio17 = vio[17, {6, 0, 1, 1, -2, 6, 7, 5, 4, -2, -1, -3, -2, 2, 1, 0}]; vio18 = vio[ 18, {1, 5, 6, 1, 3, 4, 5, 3, 1, 7, 8, 6, 8, 7, 6, 5, 4, 3, 4, 5, 6, 7, 6, 8, 9, 5, 4, 4, 3, 0, 3, 3}];
輸出
Sound[Join[viobase0, Flatten[ToExpression[ StringJoin["vio", ToString@#] & /@ Range[11]]]]]
最后輸出的是前11段旋律彬坏,因?yàn)楹竺娴木吐?tīng)不出來(lái)是卡農(nóng)了朦促。。
不能插入音頻栓始,放張圖片
音頻見(jiàn)我的微博