第8章 基于音符的制作效果
第8章 基于音符的制作效果
本章涵盖各种制作效果,可以为你的声音增添精致感和深度。所有效果都是同一主题的变化——我们不是演奏一个音符,而是演奏一系列音符,每个音符在时间或音高上稍微偏移。从这个基本技术出发,我们将完成各种效果,包括回声、琶音、合唱声音、摇摆节拍和移相器。为了创建这些效果,我们将定义一些我们使用TunePad的rewind和fastForward功能的功能。这也将给我们一个很好的机会来复习前面章节中的循环、变量和参数。一旦你掌握了这些基本技术,它将打开一系列音频效果,你可以扩展和自定义以定义你自己独特的声音。我们还将介绍如何将这些技术与其他效果和滤波器结合,以添加更多灵活性。
8.1 走调钢琴效果
让我们从较直接的效果之一开始,走调钢琴。与往常一样,你可以通过访问 https://tunepad.com/examples/out-of-tune 尝试此示例。
回想第3章,12音半音阶中分开音符之间的空间可以细分为称为分的均匀单位——只是想象钢琴键盘上每个相邻键之间有100个单独的较小音符。在像小提琴或长号这样的乐器上,你可以演奏稍微走调的音符或在音符之间滑音。我们可以在TunePad中做类似的事情,通过在调用playNote函数时使用小数而不是整数值:
playNote(36.5) # 演奏走调的C对于这一行代码,值36.5正好位于C(MIDI值36)和C♯(MIDI值37)之间的中间。换句话说,它是纯C音,失谐50分(图8.1)。

有许多艺术原因来创建走调的声音——比如如果我们想为恐怖电影创作一段诡异的旋律。为了得到这种效果,我们可以只是将旋律中的一些音符随机失谐少量,我们会得到听起来走调的东西。但一个更有趣的方法,给我们额外的纹理(和诡异的不和谐泛音),将是同时演奏几个音符,每个音符彼此稍微失谐。这实际上近似真实走调钢琴的声音。钢琴上的音符是当乐器内的锤机制同时敲击多个单独弦时产生的(大多数音符三根弦)。当那些单独弦彼此不同时,你听到的声音与仅一根弦走调得到的声音完全不同。Honky tonk钢琴被故意调音,使得每个音符的三根弦彼此稍微失谐,以获得扭曲的谐波。这是一个简单的Python函数,近似TunePad中这种不和谐的声音:
def eerieNote(note, beats = 1, velocity = 100):
volume = velocity / 3.0
for i in range(3):
offset = random() - 0.5
playNote(note + offset, beats = beats, velocity = volume)
rewind(beats)
fastForward(beats)让我们逐行遍历这个函数。如果这个示例有意义,我们在本章后面创建的所有其他函数应该更容易理解。在第1行,我们使用def关键字来定义我们自己的Python函数。
def eerieNote(note, beats = 1, velocity = 100):翻回第4章以获取函数定义的深入描述,但要记住的主要事情是,创建我们自己的函数让我们建立我们自己的音乐工具箱,以帮助创建更复杂的作品。在这种情况下,我们添加eerieNote作为我们最新的工具。我们还为这个函数定义三个参数,称为note、beats和velocity,每个都在括号内列出。我们使用note表示我们想要演奏的音高值;beats表示音符的持续时间;velocity近似声音的整体音量。你可能注意到这些参数与playNote函数完全相同。这是故意的,因为它将使在项目其他部分用我们的新eerieNote函数替换playNote函数变得容易。另一件要注意的事情是,beats和velocity是所谓的可选参数的示例。这意味着我们定义了一个默认值,如果我们没有另外指定,Python将使用它。beats的默认值是1,velocity的默认值是100。所以,例如,这些代码行中的每一个都将做相同的事情,我们可以互换使用它们:
eerieNote(36)
eerieNote(36, beats = 1)
eerieNote(36, beats = 1, velocity = 100)
eerieNote(36, 1, 100)在所有这些情况下,beats和velocity与它们的默认值相同。我们也可以用其他值调用函数:
eerieNote(40, beats = 0.5, velocity = 50)
eerieNote(40, beats = 1.5)
eerieNote(40, velocity = 120)
eerieNote(40, 2.0, 50)让我们回到eerieNote函数。在第2行,我们定义一个称为volume的变量,它将帮助我们调整个人音符的响度。
volume = velocity / 3.0我们这样做是因为以全音量演奏所有音符最终会比单个音符的声音响亮得多。我们将其值设置为velocity参数除以3.0,因为我们将最终演奏三个音符而不是一个,所以我们希望每个个人音符构成整体音量的大约三分之一。
在第3行,我们设置for循环以演奏三个音符。你也可以尝试重复不同次数的循环。记住range只是一个Python函数,它生成一系列数字[0, 1, 2],变量i将一次遍历一个,一次一个数字。
for i in range(0, 3):在第4行,我们使用Python的random函数生成0和1之间的随机小数。减去0.5然后将给我们一个在-0.5到+0.5范围内的数字。我们将结果保存在称为offset的变量中,我们将在代码的下一行使用它来移动我们的音符的音高。
offset = random() - 0.5第5行然后演奏带有我们随机音高偏移添加的音符(在-0.5和0.5之间)以使其听起来走调。注意我们使用我们的beats和volume变量来控制演奏的音符的持续时间和音量,就像我们可能调用playNote一样。
playNote(note + offset, beats = beats, velocity = volume)函数的最后两行使所有音符都在同一时间演奏。在第6行,我们将使用称为rewind的TunePad命令将播放头移回我们在演奏音符之前的位置。记住playNote自动将播放头向前推进给定的拍数,所以我们需要倒回以让我们回到开始的地方。调用rewind的效果是即时的;它所做的只是重新定位播放头。
rewind(beats)调用rewind很重要,因为我们希望所有三个音符正好在同一时间演奏,以给我们正确的效果。在本章后面,我们将尝试演奏不是全部在同一时间触发的音符。第4、5和6行都是for循环的一部分——它们都连续重复三次,因为它们缩进在第3行的循环语句下方。我们在第7行完成循环外的函数,调用另一个称为fastForward的TunePad命令。
fastForward(beats)正如你可能猜到的,这与rewind相反——它不是将播放头向后移动,而是将其向前移动。我们最后调用fastForward以使eerieNote的行为完全像我们使用标准playNote函数演奏单个音符一样。播放头将被beats的值移动。在循环末尾使用rewind与fastForward的这种组合将是我们将在本章中涵盖的所有剩余效果的标准模板。我们将混合事情,但基本思想将相同。
为了将所有这些放在一起,这里有一个童年最爱,愉快地回忆黑死病。坚持恐怖电影主题,我们将通过设置节奏低至60 BPM并使整个东西比平时低一个八度来使这额外险恶。下面列出的片段在Python列表中定义了整首歌(包括音高、持续时间和歌词),从第1行开始。每个音符由称为元组的Python结构表示,我们直到现在才在本书中使用。元组写为用逗号分隔的值——就像列表,只是你将值括在括号内而不是方括号内。我们可以完全像使用列表一样使用元组,除了元组内的值无法更改。用Python术语说同样的事情,元组是不可变对象。第18和19行逐元组遍历歌曲中的音符,为每个调用eerieNote。说note[0]获取音符的音高,note[1]获取持续时间。如果你想要打印歌词,你也可以在循环内包含这一行:
print(note[2])song = [
(48, 1, "Ring"), (48, 0.5, "a-"), (45, 1, "round"), (50, 0.5, "the"),
(48, 1.5, "ro-"), (45, 1, "sie, "), (47, 0.5, "a"), (48, 1, "pock-"),
(48, 0.5, "et"), (45, 1, "full"), (50, 0.5, "of"), (48, 1.5, "po-"),
(45, 1.5, "sies!"), (48, 1.5, "Ash-"), (45, 1.5, "es!"), (48, 1.5, "Ash-"),
(45, 1, "es!"), (45, 0.5, "We"), (48, 1.5, "all"), (48, 1.5, "fall"),
(41, 2.5, "down.")
]
def eerieNote(note, beats=1, velocity=100):
volume = velocity
for i in range(0, 3):
offset = (random() - 0.5) # 随机失谐量
playNote(note + offset, beats, velocity=volume)
rewind(beats)
fastForward(beats)
for note in song:
eerieNote(note[0] - 12, beats=note[1])8.2 移相器效果
如果你演奏前一个示例中的歌曲,你可能会听到一些有趣和意想不到的效果,特别是在较低音符上,这些效果来自一起演奏几个具有非常相似音高的音符。事实证明,这近似一种称为移相器或相移器的常见音乐效果。真实移相器效果是通过同时一起演奏同一声音的多个版本产生的,但改变每个个人声音的频率轮廓以在频谱中获得间隙或凹陷。
eerieNote函数的一个非常简单的变体替换random函数的使用,而是只是按固定量增加音高偏移变量。这种改变给了我们一个很酷的移相器效果近似,通过更改演奏的同时音符的数量或通过更改音高偏移易于操作。尝试用一些内置的TunePad乐器尝试这种效果,或使用Sampler乐器用phaserNote函数录制和回放你自己的声音。
def phaserNote(note, beats = 1, velocity = 100):
note_count = 5
volume = velocity / note_count
offset = 0.0
for i in range(0, note_count):
playNote(note + offset, beats = beats, velocity = volume)
offset += 0.15
rewind(beats)
fastForward(beats)你可以在线尝试此示例,访问:https://tunepad.com/examples/phaser
8.3 回声效果
对于下一组示例,我们将从基于音高的效果移动到基于时间的效果,在这些效果中,我们在时间上展开多个音符。这方面的最简单版本是回声效果,它以全音量演奏初始声音,然后是一系列较软音符的快速连续,这些音符落入 silence。这是在各种数字制作的音乐中使用的极其常见的技术。我们还可以加入音高操作和混响效果以添加另一层复杂性,但让我们从基础重复声音开始。与以前一样,我们将定义我们自己的函数,它看起来类似于基本playNote函数。你可以通过访问 https://tunepad.com/examples/echo 在TunePad中跟随。
def echoNote(note, beats = 1, delay = 0.125):
volume = 100 # 从全音量开始
offset = 0 # 跟踪延迟
while volume > 1: # 循环直到静音
playNote(note, beats = beats, velocity = volume)
rewind(beats - delay)
volume *= 0.5 # 将音量降低50%
offset += delay # 跟踪延迟
rewind(offset) # 按累积延迟量倒回
fastForward(beats) # 将播放头移动到音符的末尾第1行看起来类似于前两个示例,除了我们添加了另一个称为delay的可选参数,它指定每个回声音符在时间上展开多少。默认情况下,我们已将其设置为0.125拍,但通过使其成为可选参数,我们让作曲家能够在飞行中更改此延迟时间,如果他们想要的话。
第2行也应该看起来熟悉,除了这次我们将以全音量开始第一个音符,然后为每个连续音符快速衰减音量。然后在第3行,我们定义一个称为offset的变量,它跟踪到目前为止累积的总延迟量。这是一个记账变量,对于我们在函数完成后将播放头留在正确位置很重要。我们将在第9行使用这个。
在第4行,我们设置了一种新的Python循环,称为while循环。直到现在,我们一直使用for循环遍历列表或重复固定次数。另一方面,使用while循环,你将一遍又一遍地重复某些事情,直到满足某个条件——在这种情况下,循环将重复直到音量小于或等于1。
while volume > 1:基本思想是重复声音直到它太安静而听不到。使这个工作正常的技巧是在while循环内降低volume的值。否则,循环将永远一遍又一遍地重复(无限循环)。我们在第7行这样做,我们将volume乘以0.5(其先前值的50%)。我们可以在这里尝试其他值,或者甚至使其成为函数的参数,而不是硬编码值。如果你想要某物回声更长,你可以将其设置为0.6甚至0.7。再次,在这里要小心,因为如果这个值是1.0或更高,音符将永远回声,TunePad将抱怨你创建了一个无限循环!更高的值也可能导致音符回声太长并陷入其他音符,创建不需要的干扰。
第6行有点棘手。而不是像我们在前面的示例中那样一直倒回到音符的开始,我们将按较小的量倒回,以便连续音符在时间上展开。
rewind(beats - delay)这个总量等于传递给函数的delay参数。下面的图表显示了在while循环的四次迭代中这看起来像什么。你还可以看到音量的值,因为它在每次连续通过时减少。
函数的最后两行负责修复播放头位置,以便它正好在我们演奏的第一个音符的末尾,这就是我们跟踪总累积延迟量的原因。
8.4 合唱效果
与回声密切相关的一种效果是在时间上围绕中心点随机散布音符。我们用于这种效果的战略到目前为止应该看起来熟悉。唯一的棘手部分是,我们必须生成一个随机时间偏移,加减32分音符,我们用它来快进。因为这个数字可以是正的、负的或零,播放头将在我们调用fastForward时向前、向后或保持原位。另一种思考方式是,带有负数的fastForward与用正数调用rewind是相同的。这个函数接受一个称为count的可选参数,它说我们应该演奏多少散布音符。
def chorusNote(note, beats = 1, count = 4):
volume = 40
spread = 0.125
for i in range(0, count):
offset = (random() - 0.5) * spread
fastForward(offset)
playNote(note, beats - offset, volume)
rewind(beats)
fastForward(beats)然后,当我们在第8行倒回时,我们将备份到我们开始的地方。 together 这具有在音符要被演奏的时间附近随机散布几个音符的效果。你也可以尝试使spread成为你传入函数的额外可选参数。
这是一个使用chorusNote的简单 stomp/clap 模式:
stomp = [ 0, 1 ]
clap = 22
chorusNote(stomp)
chorusNote(stomp)
chorusNote(clap)
rest(1)这是与混响效果结合的好效果,以使其听起来像你在一个大房间里有 crowd。另一种常见技术是将每个音符的音高彼此稍微失谐,这是1980年代应用于电吉他的合唱效果的常见技术。你可以通过访问 https://tunepad.com/examples/chorus 尝试这个函数。
8.5 琶音效果
另一种极其常见的效果称为琶音,用于将单个持续音符转换为快速在和弦结构上上下爬行的节奏模式。我们在间奏4中将其作为演奏和弦的方法看到了。琶音通常用于从古典到嘻哈到舞曲的广泛音乐流派,大多数数字音频工作站(DAW)提供内置琶音器,具有各种选项来更改速度、方向和音符模式。按照我们在前面函数中看到的模式,我们可以通过创建带有音符模式和速度参数的ARPNote函数在TunePad中构建琶音器。这种效果结合了基于音高和基于时机的音符变化。
def ARPNote(note, beats = 1, pattern = [0,4,7], speed = 0.125):
offset = 0
while offset < beats:
for step in pattern:
playNote(note + step, speed)
offset += speed
rewind(offset)
fastForward(beats)在我们将这个放在完整示例中之前,让我们看看pattern参数。这个参数是一个描述从第一个音符(由note参数给出)的音高偏移的列表。函数将遍历这个列表,每个元素将被添加到note以计算要演奏的音符。pattern参数可以像你想要的那样简单或复杂,但一个好的起点是我们在第3章中介绍的一些和弦。这里有一些常见的琶音模式:
- 大三和弦:[ 0, 4, 7 ]
- 小三和弦:[ 0, 3, 7 ]
- 大三和弦上下:[ 0, 4, 7, 12, 7, 4 ]
- 小三和弦上下:[ 0, 3, 7, 12, 7, 3 ]
这个函数是在Python中使用嵌套循环的好例子,这只是一个循环嵌入另一个内。外循环在第3行设置并重复直到变量offset大于音符的持续时间。内循环在第4行设置并遍历pattern参数中的每个值。这一切意味着内for循环将至少运行一次,可能很多次——只要它需要完全填充beats参数提供的音符持续时间。第5行通过将step添加到基本音符来演奏琶音中的音符,以便它向上或向下移动模式,我们将音符的持续时间设置为speed。然后在第6行,我们按琶音步骤的持续时间增加offset记账变量。函数的最后两行清理时机以确保播放头按正确的量前进。
speed参数是品味和音乐惯例的问题,但使用16分音符(0.25拍)或32分音符(0.125拍)作为此值很常见。你可能注意到的一件事是,这个函数将重复琶音和弦模式,只要它需要完全填充整个音符持续时间,但它也可能演奏超出音符的末尾。这种额外的停留可能是不可取的,取决于我们要制作的音乐。要修复这个问题,我们可以在第6行之后直接在for循环内插入一个额外的行。
if offset >= beats: break这具有一旦我们达到所需长度就退出循环的效果,可能使ARP模式短路。在我们看看ARPNote函数运行的示例之前,让我们再添加一个功能。让琶音的每个音符都以相同的velocity敲击听起来有点重。为了添加更有趣的节奏和纹理,我们可以改为强调琶音的第一个音符,然后将剩余音符的音量降低。这是ARPNote函数的一个变体,它用我们在echoNote示例中使用的技术创建了这种效果。
def ARPNote(note, beats = 1, velocity = 100, pattern = [0,4,7], speed = 0.125):
offset = 0
while offset < beats:
volume = velocity # 每次迭代重置音量
for step in pattern:
playNote(note + step, speed, volume)
volume = velocity * 0.25 # 在第一个音符后将音量降低到四分之一
offset += speed
if offset >= beats: break
rewind(offset)
fastForward(beats)发生的事情是我们创建一个volume变量,它在while循环的每次迭代中重置为velocity参数的完整值。然后,在我们在for循环内演奏琶音的第一个音符后,我们将剩余琶音音符的音量降低到velocity的四分之一。当琶音完成时,volume恢复为其原始值,用于下一个琶音。
这个项目用The Police的示例将所有东西放在一起。在 https://tunepad.com/examples/arp 尝试此代码。当你在线尝试时,你可能注意到我们在第5行的ARPNote函数中添加了一个更多的技巧。这使用playNote的sustain参数让琶音的第一个音符为整个集合的持续时间响起,但以降低的音量。这给琶音一个很好的共振质量。
8.6 摇摆效果
本章的最后一个效果从标准直节奏创建摇摆节拍。基本上,这意味着为节奏的时机添加反弹或摇摆,以便我们从机械精度移动到更多的人类感觉。大多数DAW提供各种选项来摇摆节拍。通常这涉及在8分或16分音符级别改变节拍,以便奇数编号的音符在时间上稍微伸展,而偶数编号的音符被压缩相同的量。大多数DAW让你通过提供固定选择的选择或连续拨号来选择偶数和奇数编号音符之间的比率。在TunePad中创建类似的东西结果相当直接。最困难的部分是弄清楚我们是在偶数还是奇数拍上。为此,我们可以使用内置的TunePad函数getPlayhead(),它返回播放头的当前位置(以拍为单位,四分音符)。要弄清楚我们在哪个8分音符上,我们可以将8分音符持续时间(下面第3行上的0.5)除以。我们使用Python的round函数确保这是一个整数值。下一步是询问我们是在偶数还是奇数8分音符上。我们在第4行使用模运算符(%)这样做。你可以将其视为返回除法操作的余数。换句话说,将step变量除以2。如果余数是1,它是偶数8分音符,我们需要通过我们在第2行定义的摇摆因子将音符向前推一点。否则,它是奇数8分音符,我们将其留在原地。 together 这与伸展奇数编号音符的持续时间具有相同的效果。
def swingNote(note, beats=1, velocity=100):
swing = 0.25
step = round(getPlayhead() / 0.5)
if step % 2 == 1:
fastForward(beats * swing)
playNote(note, beats, velocity)
rewind(beats * swing)
else:
playNote(note, beats, velocity)这个示例编写了一个使用swingNote的简单摇滚节拍。在 https://tunepad.com/examples/swing 在线尝试。尝试调整第2行上的摇摆因子的值,以感受它如何为节奏添加反弹。将摇摆设置为0.0以获得直节拍。