如今,许多人尝试用计算机创作乐器,普遍方法是随机生成一段音乐,和现有曲子的相似度进行打分,一个分值范围内算通过。我也这么做?不,这样做效率低下,随机生成几千首只有一首通过,计算速度也十分低下(超级电脑不说),筛选出的曲子也不一定好听。
我用什么方法呢?今天,我们要了解许多令人发指的乐理,以及计算令人发指的乐理公式。准备好笔纸了么?今天,就让我,带您进入美妙复杂的音乐殿堂吧!
乐理的代码:
废话不多说,先来讲讲“音程”:
音程及其算法:
看着玄乎,其实是最简单,它表示两音之间的“距离,其基本单位称为度。在mido中,以“半音”为基本单位,接下来,我都采用半音计数。
1:**小二度**2:**大二度**/减三度3:**小三度**/增二度4:**大三度**/减四度5:**纯四度**/增三度6:**增四度**/减五度7:**纯五度**/减六度8:**小六度**/增五度9:**大六度**/减七度10:**小七度**/增六度11:**大七度**(**单位:****半音**)
除了四度和五度(八度不算),度按减小大增来计算,没有基准。但,一般“大度”为最佳选择。不信可以尝试下,是大三度好听,还是小三度好听。除四度以外,只有理论上的增减,不会说增三度,只说纯四度。因此,只需做11个函数就行了。比如说小二度:
defsd_two(low=None,high=None):就是转换,前面的代码都写过yin=[]iflowandhigh==None:high=low+1ifhighandlow==None:low=(low)(high)returnyin
三和弦:
三和弦有四类,大三和弦,小三和弦,增三和弦,减三和弦。七和弦较复杂,有兴趣读者可自己搜搜。
大三和弦结构是:大三度+小三度。小三和弦结构是:小三度+大三度。增三和弦结构是:大三度+大三度,减三和弦结构是:小三度+小三度。最舒服的和弦是大三和弦,最恶心的和弦是减三和弦。
因此,我们只要知道一个音,就可以求出其他的音。我在这贴大三和弦代码:
defb_three(geng=None,zhong=None,wu=None):yin=[]ifgengandzhong==Noneandwu==None:知道中音geng=zhong-4wu=zhong+3····知道五音zhong=wu-3geng=zhong-4····前面有yin=[]ifgengandzhongandwu:若是第一转为(三和弦)geng+=12(zhong)(wu)(geng)returnyinifzhong-geng==5andwu-zhong==4:和声版pig=int(beat(time))上篇文章有,看看else:ifchord==Noneanddu==None:···和弦ifchord=="dasan":此处省略一千行小二度ifnote=="low":fu[i]=sd_two(fu[i])ifnote=="high":fu[i]=sd_two(high=fu[i])····循环forxinrange(len(fu[i])):yin(fu[i][x],pai[i]*pig,liang=high,unit=tra[x],qi=yue)
有太多的“音程”、“和弦”,这不可能全贴.
庆祝一下,我用这函数,给《玛丽有只小山羊》配了和弦和音程,只有你没想到,没有我做不出
巴洛克曲子算法及实现:
巴洛克时期有许多不同的种类曲子,二部曲,三部曲,四部曲,宾格,赋格……数不过来,不同种类的曲子有不同形式。今天我们实现二部曲。二部曲有很多形式,单开式,双起式,加厚式……我们挑个简单的,“单开式”。
《巴赫二部创意曲》第一首就是讲这个。讲之前,要贴几段代码:
倒影:
打个比方:[3,4,5]的倒影就是[3,2,1]。这形式在巴洛克时期全都是,实现函数:
defdao(yin):#计算倒影a=yin[0]*2daoyin=[]foriinyin:b=(b)returndaoyin
首音乘2,以此减接下来的数,得出数组(list)
倒影难道音高不变了?总要变吧。动动脑经,得出答案:
defgetdao(xuanlu,base):foriinrange(len(xuanlu)):iftype(xuanlu[i])==str:xuanlu[i]=num(xuanlu[i])iftype(base)==str:base=num(base)xuanlu=dao(xuanlu)high=base-xuanlu[0]foriinrange(len(xuanlu)):xuanlu[i]+=highreturnxuanlu
以base位基音,得出xuanlu倒影。
分拆和弦、时间:
在巴洛克时期,总会把主题(主旋律)拆开来,分成个主题。但你不知道用户会输入怎样的节奏型。再动动脑筋,就可以把旋律按节拍的不同拆开。
defgetlu(first,second,ind):s=0c=0foriinrange(1,len(second)):ifsecond[i]!=second[s]:c+=1ifc==ind:returnfirst[s:i]else:s=ireturnfirst[s:]
同理,分拆时间:
defgettime(paizi,ind):s=0c=0foriinrange(1,len(paizi)):ifpaizi[i]!=paizi[s]:c+=1ifc==ind:returnpaizi[s:i]else:s=ireturnpaizi[s:]
这样你就可以获取任意一段的代码和时间了。
计算机计算乐曲实现:
有小白生气了,算法还不讲!别急,算法这不就来了?那最经典的BWV772举例:
此图版权为作者所有!我们用蓝色框匡主题,绿色框匡副题和配旋律。****用黄色代表倒影。我们用数学的语言总结下:(我画的)
有个特别的。所有的曲子都要“解决”,“解决”是较复杂,有兴趣的可以搜搜。这我自己做了个个性化解决,大家可以拿来用。
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)此解决方法严禁抄袭。到这,相信只要智商100,就可以写出来。但,许多的小白还是不会写。为了照顾小白,我原来想在这里贴,但是实在太长,放不下。
结语
现在你可以通过计算机计算出巴洛克时期的二部曲的开场事了,只要有个好旋律,就可以出个好曲子。但其他的种类呢?可以买本《巴赫创意曲集》,一共30首曲子,每首曲子都很经典。可以自己挨个分析写代码哦。