您現在的位置是:首頁 > 垂釣
5分鐘曲子能不重樣連續播放451天?程式設計師喜歡上什麼東西,真是…
- 由 量子位 發表于 垂釣
- 2022-06-11
123153252是什麼曲子
乾明 發自 凹非寺
量子位 報道 | 公眾號 QbitAI
程式設計師要是喜歡上一個東西,指不定會搞出什麼“瘋狂”事情來。
今天要說的,是特別喜歡一首曲子的程式設計師
貝特
(Alex Bainter)。
這首曲子,名為
aisatsana
,來自電子樂大師Aphex Twin,只有5分多鐘。
讓他很苦惱的是,單曲迴圈聽著容易膩歪,他想讓這個曲子能一直不重樣地播放下去。
然後,他選擇了馬爾可夫鏈……
現在這首曲子已經能夠不間斷播放451天不重樣……
貝特把完成這一“壯舉”的過程寫成了文章,分享了出來,而且,
程式碼已經開源
。
在Hacker News很快就獲得了400多熱度,200多條評論。
不少人評論稱,這樣聽歌真的很爽, 實現起來很簡單,但效果很好!
它到底是怎麼做的呢?我們一起來看看。
從演算法的角度理解一首曲子
想要曲子不重樣地播放下去,首要的任務就是要理解曲子的結構。
一般情況下,播放曲子的速度可以BPM(beats per minute)來衡量。
aisatsana這首曲子很簡單,共有102BPM。如果從第一個音符開始計數的,每16個節拍包含一系列音符,他稱之為
樂句
(phrase),整首曲子中,一共有32個樂句。
想要建立一個能夠不間斷、不重複播放aisatsana的系統,演算法需要滿足以下兩個要求:
知道一個樂句什麼時候結束。
播放不重樣的樂句。
第一個要求,相對來說非常簡單,只是計時。第二個要求,是最棘手的部分。
讓曲子一直播放下去
一種簡單的策略是,編寫一個程式,粗暴地把32個樂句拆分開,一個樂句之後,隨機播放另一個。
這種方式,雖然相互銜接上沒有問題,聽起來也比單曲迴圈更加靈活有趣,但本質上也是重複的。
只要熟悉了這32個樂句,曲子依舊會無聊。
怎麼辦?答案只有一個:
創造一個系統,來生成聽起很與原來樂句很相似的新樂句。
最直接的方法,就是深度學習技術了。但只有32個樂句的樣本……很顯然不太現實。
最後,貝特就把目光轉向了
馬爾可夫鏈
這個“老方法”。
馬爾可夫鏈,能夠記錄一組狀態中,從一個狀態轉移到另一個狀態的機率。
舉例來說,你生活中只去3個地方:家、公司和商店,也就是說,你要麼在家裡,要麼在公司,要麼在商店。
想要的知道你接下來要去哪?首先就是記錄你一段時間內去這三個地方情況,根據記錄資料來分析相關的可能性。
比如說,當你在家的時候,你有80%的可能性去公司,你在公司的時候,回家和去商店機率都是50%,如果你在商店,接下來回家的可能性就有95%。
以上,就是建立一個馬爾可夫鏈的所需要的一切:狀態,以及從一個狀態到另一個狀態的機率。
如果把它應用到音樂上,該怎麼做?
馬爾可夫鏈生成新樂句
先來看一張圖:
圖中展示的是兩個樂句,每個有4個節拍,每個音符旁邊,是音符的名字,最上面是節拍。播放這些樂句的順序,是從左到右依次進行。
然後,把兩個樂句放到馬爾可夫鏈中,狀態命名為節拍與音符的組合,比如1A就是在第一個節拍的時候演奏A音符。
除了這些,還需要有開始和結束的狀態,來表示樂句的開始和結束。用箭頭來表示一個狀態到另一個狀態的轉變。
在上圖中,第一個樂句就是開始→1A→2F→3A→4F→結束。第二個樂句是開始→1E→2C→3A→4C→結束。
這裡面,一共有9個狀態,分別是開始、1A、1E、2F、2C、3A、4F、4C和結束。從一個狀態到另一個狀態的機率是:
開始→1A:50%
開始→1E:50%
1A→2F:100%
1E→2C:100%
2F→3A:100%
2C→3A:100%
3A→4F:50%
3A→4C:50%
4F→結束:100%
4C→結束:100%
這樣,就建立了一個馬爾可夫鏈。從開始到結束,所有可能的路徑,可以生成4個樂句:
開始→1A→2F→3A→4F→結束(原始樂句1)
開始→1A→2F→3A→4C→結束(新樂句)
開始→1E→2C→3A→4C→結束(原始樂句2)
開始→1E→2C→3A→4F→結束(新樂句)
就這樣,馬爾科夫鏈就生成了兩個新的樂句!因為是透過同一個鏈構建的,聽起來也會非常相似。
在這個例子中,只是用了2個樂句,每個樂句中4個節拍。而aisatsana中有32個樂句,每個樂句16個節拍。
按照這個邏輯,貝特最後生成了400多萬個獨特的樂句,可以播放超過451天,而且所有的樂句都不會重複……
整個實現程式碼,貝特已經開源了。搜pieces-alex-bainter就能找到。
—
完
—