在这个博客中,我将介绍我的自动音乐创作方法,包括理论、算法和Python包实现ch0p1n。
举一个简单的例子,想象你把一只猫放在钢琴上,随机按下键来产生音乐。因此,音乐是预先确定的算法的结果,而不是你瞬间的情绪或作曲技巧的结果。这就是为什么它被称为自动合成。
自动作文有许多不同的方法或范例。1我采取的方法受到了阿诺德·勋伯格、海因里希·申克和威廉·卡普林理论的启发。关键的想法是,在一些常见的操作下,音乐可以从有限的材料中发展或产生。我将在以下三个部分中解释我的方法的理论基础。
让我们来看一个例子,贝多芬第一首钢琴奏鸣曲的开头:
事实上,蓝色框架中的结构可以仅通过转置红色框架中的结构来生成。因此,为了创作这篇文章,我只需要在红色框架中创建结构,然后重用或稍微修改它以生成蓝色框架中的结构,而不是从头开始创建两个结构。
同样的情况也发生在其他地方。如下所示,四个框架结构也非常相似:
这种重复使用是否只存在于贝多芬的音乐中?不,这可能发生在每一部音乐作品中。无论一部音乐作品持续多长时间,或者它的声音有多变化多端,其核心材料的数量总是很少的。
然而,有时候,一种材料可以被修改得太多以至于你几乎认不出来,比如在下面的例子中,肖邦的夜曲作品9第一首的开头:
这两个框架结构看起来和听起来都非常不同,但在我的方法中,蓝色框架中的结构仍然可以通过在红色框架中详细阐述结构来生成,而不是它们完全不相关。这是因为这两个结构有一些共同的形态特征,它们具有相同的背景和声级数,并且从音乐形式的角度来看,蓝色框架中的结构确实是红色框架中结构的重复。2.
请注意,在声明一个结构可以由其他结构生成时,我并没有断言贝多芬或肖邦在作曲时确实这样做或故意这样做。相反,我的观点是,我们可以使用这种音乐生成的视角来正式化或自动化音乐创作的过程。
一旦创建了一个结构,就可以对其应用一些常见的操作来生成新的结构。我将在下面讨论一些操作。
我要讲的第一个操作是重复。它意味着在不改变形态的情况下,以新的和谐方式重复一个结构。
蓝色框架中的结构是红色框架中结构的换位。这两种结构具有相同的形态,尽管它们适应不同的背景和声。
肖邦的夜曲是另一个例子。蓝色框架中的伴奏主题与红色框架中的主题重复:
在重复中,根据一些语音引导规则,一些音调会移动到最近的音调以适应新的和声。3其中一些变化如下所示:
下一个操作是精化。这意味着向结构中添加传递注释、相邻注释和其他类型的注释。肖邦的夜曲就是一个例子,在重复中加入了许多元组:
有时,详细描述更多地是从分数中推断出来的,而不是表现在分数中。海因里希·申克(Heinrich Schenker)的理论区分了音乐的表层结构和深层结构,表层结构是深层结构细化的结果,如下例所示:
例如,在上面的分数中,b部分可以通过阐述c部分生成。
精化的相反操作是简化。例如,在上述分数中,b部分可以减少为c部分。
我要说的最后一个操作是碎片化。这意味着从材料中取出一块碎片。
正如贝多芬的奏鸣曲一样,蓝色框架中的结构是红色框架中的一个片段:
可以修改红色框架中的片段以生成橙色框架中的结构;蓝色框架中的片段可以修改以生成绿色框架中的结构。这两块碎片取自紫色框架中的结构。
有更多的操作可以应用到音乐材料上,但我就到此为止。我所介绍的四个操作对于本博客来说已经足够了。
根据音乐形式,创建和生成的结构可以组合成更大的结构。音乐形式是音乐材料组织的一种方式。
例如,贝多芬奏鸣曲的开头有形式句。下面是威廉·卡普林的系统是如何分析这句话的:2
肖邦夜曲的开始是从一个更大的结构形式复合时期,这是远比句子复杂。
我不会在这里深入讨论音乐形式的问题。我强烈推荐威廉·卡普林关于这个话题的优秀教材2。我的重点是,音乐材料应该根据音乐形式进行组合,以产生有意义的音乐。
我们首先需要严格定义音乐材料和结构,我们一直在模糊地谈论这些。
让我们回到贝多芬的奏鸣曲。下面是它的前两个栏:
这首曲子有两种声音或乐句。每一段音乐都由音符、休止符或和弦组成,而和弦也由音符组成。音符有几个属性,这里只考虑音高和持续时间。我们将分别处理音符的音高和持续时间内容,而不是将音符表示为单个对象。
音高可以用科学的音高符号或MIDI音符数字来表示。为了便于操作,通常使用后者。例如,音高C4由MIDI音符编号60表示。
在Python中,和弦的音高内容可以用列表表示。例如,在Python中,我们可以使用[';C4';,';A-3';,';F3';]或[60,56,53]代表红色框架中和弦的音高内容:
持续时间可以用数字表示。例如,季度票据的持续时间为1。
一条音乐线的音高内容可以用我所说的音高线来表示。在Python中,音高线是一个列表,其成员为无、数字或数字列表。使用Python包类型,节线可以定义为:
一条音乐线的持续时间内容可以用持续时间线来表示。在Python中,持续时间行是成员为数字的列表。
最后,和声和音阶可以用音高等级列表来表示。例如,在Python中,C大调和声可以用[';C';,';E';,';G';]来表示或者[0,4,7]。
你可能经常听到这个词。母题在结构上是一条音乐线,通常长度较短。主题是音乐的基石。它们可以被重复、细化、分割和组合,从而产生音乐。
例如,以下是勋伯格如何分析贝多芬奏鸣曲的开头:5
在他的分析中,这首曲子的旋律部分只能由三个主题生成。
有不同种类的图案。例如,以下乐谱中有两种主题:
红色框架中的图案可以称为伴奏图案,因为它们出现在这首夜曲的伴奏行中。它们也可以被称为和声母题,因为它们只包含和声音符。蓝色框架中的主题可以称为旋律主题,因为它们出现在旋律线中,或者如果它们包含非和声音符,则称为非和声主题。
在接下来的几节中,我将讨论可应用于Motif的常见操作的实现。
我的Python包ch0p1n中的函数transpose()用于沿比例变换图案。
音高主题=[60,67,76,72]#[#39;C4';';G4';';E5';';C5';]持续时间主题=[1,1,1,1]
我们可以用show()在score中显示这个主题,它构建在Python包music21上:
来自ch0p1n。utils import show(音高线=[pitch_motif]、音长线=[duration_motif]、组=1、#高音杆键中的声音数=0、米=和#39;4/4和#39;、谱号=[和#39;g和#39;,';f和#39;]))
来自ch0p1n。motif import transpose pitch_motif_transposed=transpose(pitch_motif=pitch_motif,scale=[0,2,4,5,7,9,11],step=1)
显示(音高线=[pitch_motif_transposed],duration_lines=[duration_motif],group=1,#高音杆键中的声音数=0,meter=';4/4';,谱号=[';g';,';f';]))
看起来不错。每一个音高都在C大调音阶上上升了一步。
由于和声是一种特殊的音阶,我们可以使用转置()在和声中重复主题,比如G大调和声:
音高调换=调换(音高调换=音高调换,音阶=[7,11,2],#G大调和声阶=1)
表演(音高线条=[音高主题+音高主题转置],音长线条=[音长主题*2],组=1,键=0,节拍=';4/4';,谱号=[';g';,';f';]))
最初的主题在第一栏,第二栏转置。你可以看到G大调和声中的每个音高是如何上升一步的。
然而,在某些情况下,transpose()并不好用。仍然在上面的例子中,假设我们用step=-1将motif向下转一步,而不是向上转一步:
第二小节中的转置主题是不可接受的,因为它没有音高等级G来完全具体化G大调和声。
我们可以通过ch0p1n中的函数lead()来改善这种情况。这个函数的名字来源于声音引导的概念,意思是一个主题中的每个音符都一步一步地引导到一个给定和声中的音符。
来自ch0p1n。motif import lead pitch_motif=lead(pitch_motif=pitch_motif,harmony=[7,11,2],35;G大调和声步数=[-1,0],complete=False,Simular=None)
步数=[-1,0]意味着每个音高如果符合和声,将移动零步,同时向下移动一步。换句话说,每个音高可能会在lead()下的给定和声中生成多个音高,因此返回的结果是音高主题列表,而不是单个。稍后我将讨论完整参数和类似参数。
#合并itertools导入链展示中的'pitch_Motions'(pitch_lines=[列表(链(*pitch_Motions))],duration_lines=[duration_motif*2],group=1,key=0,meter=&39;4/4' , 谱号=[';g';,';f';])
虽然第一小节中的主题与转置()产生的不可接受的主题相同,步骤=-1,但第二小节中的主题是好的,这充分体现了G大调和声。
使用complete=True,我们可以筛选出不和谐完整或不完全具体化给定和谐的音高主题:
音高母题=引导(音高母题=音高母题,和声=[7,11,2],步数=[1,0],完整=正确,相似=无)
在参数相似的情况下,我们可以筛选出与原始基调轮廓不同的基调图案。在这篇介绍性博客中,我将跳过这一部分。
函数thread()用于在连续的和声中重复一个主题,或在和声中穿插一个主题。让我们尝试一下前面定义的主题:
来自ch0p1n。motif import thread pitch_motif=thread(pitch_motif=pitch_motif,duration_motif=duration_motif,和声=[5,9,0],[7,11,2],#F,G durations=[2,2],steps=[1])show(pitch lines=pitch_motif,duration_lines=[duration_motif]组=1,键=0,米=39;2/4' , 谱号=[';g';,';f';])
主题的前两个音符改编为F大调和声,而最后两个音符改编为G大调和声。
到目前为止,我只讨论了和声主题。为了处理非谐波图案,这是更复杂的,我们首先需要考虑如何精心制作图案。
简单地说,精化就是给主题添加注释。ch0p1n中的函数deployate()正好用于此目的。
来自ch0p1n。motif import deployate motif=deployate(音高=pitch_motif,持续时间=duration_motif,参考=2,步数=1,-1],音阶=0,2,4,5,7,9,11],位置=39;左';)
表演(音高线=[pitch_motif+motif[0]],持续时间线=[duration_motif+motif[1]],组=1,键=0,音阶=';4/4';,谱号=[';g';,';f';]))
参数引用指示在何处添加注释或阐述主题。例如,reference=2表示在第三个注释处添加注释。我们可以详细说明最后一点:
motif=精心设计(音高#motif=音高#motif,持续时间#motif=持续时间#motif,参考=3,#最后一个音符步数=[-1,-1],音阶=[0,2,4,5,7,9,11],位置=';左';)
参数步骤指定要添加的音符的音高。例如,steps=[-1,-1]表示参考注释应向下移动一步以生成第一个注释,然后此注释应向下移动一步以生成第二个注释。让我们用这个参数添加三个降序注释:
motif=精致(音高#音高#音高#音高#音高#音高#音长#音高#音高#音长#音高#音高#音高#音高#音长#音高#音长#音高#音高#音高
通过这些步骤,您还可以重复一些注释或为主题添加休息,如以下示例所示:
motif=精心设计(音高_motif=音高_motif,持续时间_motif=持续时间_motif,参考=2,步骤=[0,0,无]#重复两次音符,然后添加休息)
参数比例指定移动参考注释以生成要添加的注释的比例。例如,scale=[0,2,4,5,7,9,11]表示它是C大调音阶。我们可以用C色阶来代替:
motif=精细(音高#motif=音高#motif,持续时间#motif=持续时间#motif,参考=2,步骤=[-1,-1],音阶=列表(范围(12)),#C色阶位置=';左';)
参数位置指定添加注释相对于参考注释的位置。例如,position=';左';指示将注释添加到参考注释的左侧。我们可以在右边添加注释:
motif=精心设计(音高#motif=音高#motif,持续时间#motif=持续时间#motif,参考=2,步数=[-1,-1],音阶=[0,2,4,5,7,9,11],位置=';右侧';#在右侧添加注释)
请注意,带有';左';和';对';,添加的注释采用参考注释的持续时间。如果你想从参考注释之前或之后的注释中提取持续时间,请使用';前';或';接下来';。例如
motif=精心设计(音高#motif=音高#motif,持续时间#motif=持续时间#motif,参考=2,步数=[-1,-1],音阶=[0,2,4,5,7,9,11],位置=';上一个';#从上一个音符中选取持续时间)
参数比率指定添加的笔记持续时间的百分比。例如,比率=1/2意味着添加的注释占参考注释持续时间的50%:
motif=精心设计(音高#motif=音高#motif,持续时间#motif=持续时间#motif,参考=2,步骤=[-1,-1],音阶=[0,2,4,5,7,9,11],位置=';左';,比率=1/2#占参考音符持续时间的50%)
精简与精化相反。这是从一个主题中删除注释。ch0p1n的相应函数是reduce()。
来自ch0p1n。motif import reduce motif=reduce(音高motif=motif[0],持续时间motif=motif[1],开始=2,结束=3,位置=';右';)
参数start和end指定要删除的注释。参数位置指定要向其添加已删除注释的持续时间的参考注释。
背景和声为Fm,圆圈音符不符合和声,因此为非和声。
音高主题=[65,68,72,77,80,79,77,76,77,无]持续时间主题=[1,1,1,1,1.5,1/6,1/6,1/6,1,1]
音高主题,持续时间主题=减少(音高主题,持续时间主题,开始=5,结束=7,位置=';左';)#以下显示相同([pitch_motif],[duration_motif],key=-4)
音高主题,持续时间主题=精心设计(音高主题,持续时间主题,参考=4,步数=[-1,-1,-1],音阶=[5,7,8,10,0,1,4],位置=';右';,比率=1/4)
碎片化是将一个主题分解成几个较短的主题,或从一个主题中提取一个片段。ch0p1n中相应的函数是divide()和fragment()。
音高主题=[82,84,85,81,82,78]+[77]*4+[78,77,75,72,73,70]持续时间主题=[0.5]*6+[1]*4+[0.5]*4+[2,1]
使用divide(),我们可以将这个图案分成三个长度相等的较短图案:
>>>;主题[([82,84,85,81,82,78,77],[0.5,0.5,0.5,0.5,0.5,1]),([77,77,77,78,77],[1,1,1,0.5,0.5],[75,72,73,70],[0.5,0.5,2,1])]
来自ch0p1n。motif import fragment motif=fragment(音高、持续时间、开始=6、结束=9、比率=1/2、适合度=';右';)显示([motif[0],[motif[1],[key=-5,meter=';6/4';)
参数start和end指定片段的开始注释和结束注释。比率=1/2表示片段的长度应该是原始图案的50%,为了实现这一点,fit=';右';表示尾音应该延长。
现在是时候把这一切放在一起了。首先,我们试着用少量的材料,在我们已经讨论过的操作下,生成贝多芬奏鸣曲的开头。
为了简化问题并使模式更加清晰,我将从原始乐谱中删除含糊、发音、动态、优雅音符和其他一些音符:
这首曲子由两个声部或乐谱组成,高音管中的旋律线和低音管中的伴奏线。
总之,要创作贝多芬奏鸣曲的开头,核心材料是
旋律音高主题=[65,68,72,77,80,77]旋律音长主题=[1,1,1,1,2,2]
#Fm,C7,Fm,C7,Fm,Gdim,C7和声=[[5,8,0],[0,4,7,10],[5,8,7,10],[5,8,0],[7,10,1],[0,4,7,10]#F谐波小调音阶=[5,7,8,10,0,1,4]
def生成贝多芬奏鸣曲(旋律、音高、旋律、音长、伴奏、伴奏、音高、和声、,
......