TuttiCodeTuttiCode 指南

自动化

用 ramp() 做渐变,用 env() 画点和曲线,再加上模式和信号——让设备参数、推子和发送随时间变化,和“在 TuttiDAW 中打开”后显示的自动化完全一样。

设备参数不必一成不变。给它一个模式,它就逐个循环地变化;给它一个信号,它就平滑地扫动。这就是用代码写的自动化:“在 TuttiDAW 中打开”会把它显示为声部片段上的包络,在 /code 上声部也按同样的方式播放。

值 设备得到的是
0.4、"4s"、slider(0.4) 一个保持不变的设置
ramp(-60, 0, 4) 4 小节内从 -60 直线变到 0,然后重来
env("0:200 2:4000~.5 4:200") 用直线和曲线连接起来的点
"<0.1 0.6>"、"0 0.5 1 0.5" 每个事件处一个台阶:值一直保持到下一个事件
sine.range(300, 3000) 平滑的扫动,每个循环采样 16 次

和 .inst、.fx、.midifx 本身一样,这是 TuttiDAW 独有的功能。

渐变:ramp

ramp(from, to, bars) 是在若干小节内从一个值到另一个值的直线。给底鼓的推子做一个 4 小节的淡入:

kick: s("bd*4").mix({vol: ramp(-60, 0, 4)})
在 /TuttiCode 中打开

之后渐变会重新开始,就像模式会循环一样。加上 .once(),它就从程序开头只播放一次,然后保持最后的值:

pad: note("<c3 eb3 g3 bb3>").s("sawtooth").release(0.3)
  .mix({vol: ramp(-60, -6, 8).once()})
在 /TuttiCode 中打开

程序的循环会变长,盖住渐变或包络(这里是 8 小节),所以在 /code 上能听到完整的变化。

点、直线和曲线:env

env("...") 用 position:value 点画出任意形状,点之间用直线连接。位置以小节计(1.5、3/4);值使用参数自己的单位,可以带单位("-6dB"、"2kHz"):

pad: note("c3").s("sawtooth")
  .fx("Auto Filter", {frequency: env("0:200 2:4000~.5 4:200")})
在 /TuttiCode 中打开
写法 含义
2:4000 第 2 小节处值为 4000,一条直线通向这里
2:4000~.5 结束于此的线段弯曲(-1..1;正值在起点附近停留更久,和工作室里的曲线一样)
_2:4000 保持之前的值直到第 2 小节,然后跳变
2:0 2:1 同一位置的两个点:跳变

包络按最后一个位置循环。第二个参数可以让循环更长:env("0:0 2:1", 4) 先上升两小节,再保持两小节。在第一个点之前,它保持第一个值。

精确形式

工作室还可以把曲线存成贝塞尔曲线(Live 的曲线手柄)。代码把它写成点的列表,每个点是 [position, value],可以带一段线段:{curve: k}、{curve: [x1, y1, x2, y2]} 或 "hold":

lead: note("c4 eb4 g4").s("sawtooth")
  .mix({pan: env([[0, -1], [2, 1, {curve: [0.2, 0, 0.8, 1]}], [4, -1, "hold"]])})
在 /TuttiCode 中打开

很少需要手写它:工作室里的“复制为 TuttiCode 代码”会写出能精确保留自动化的最短形式——ramp、env 字符串,或者这个列表。

每隔一小节更湿的混响

"<0.1 0.6>" 在第一个循环是 0.1,第二个循环是 0.6:

pad: note("<c3 eb3 g3 bb3>").s("sawtooth").release(0.3)
  .fx("Reverb", {dryWetBalance: "<0.1 0.6>", decayTime: "3s"})
在 /TuttiCode 中打开

decayTime 是常量,所以一直是 3 秒。同一个设备的多个参数可以同时变化,各用各的模式。

滤波器扫频

信号是连续变化的。sine.range(300, 3000) 每个循环从 300 Hz 升到 3000 Hz 再回来;.slow(4) 把它拉长到四个循环:

bass: note("c2*8").s("sawtooth")
  .fx("Auto Filter", {frequency: sine.range(300, 3000).slow(4)})
在 /TuttiCode 中打开

这样程序会在四个循环后重复,和任何四个循环才变一轮的模式一样。

单位、乐器和 MIDI 效果器

模式接受的值和常量一样,用参数自己的单位:带单位的字符串会被换算("<-6dB 0dB>"、"<1s 4s>")。乐器参数也能自动化:

lead: note("c4 eb4 g4 bb4").inst("Drift", {cutoff: "<400 1200 2400 800>"})
  .fx("Utility", {gainDb: "<-6dB 0dB>"})
在 /TuttiCode 中打开

选项类参数在它的名称之间跳变。在模式里,Arpeggiator 的 rate 名称(1/16、1/8)按名称读,不当作除法:

arp: note("[c3,e3,g3]").midifx("Arpeggiator", {style: "<Up Down>", rate: "<1/16 1/8>"})
在 /TuttiCode 中打开

带空格的名称("Up & Down")不能作为模式里的一步:请用它的序号。百分数("30%")只能写成常量,因为 % 在迷你记法里另有含义——在模式里请写 0.3。

总线、编组和 master

总线、编组和 master 也能这样变化:它们的 .mix({vol, pan})、编组的 .send(bus, level) 以及它们设备的参数都可以用模式和信号。

bus("verb").fx("Reverb", {dryWetBalance: 1, decayTime: "<2s 6s>"})
  .mix({vol: sine.range(-18, -6).slow(4)})
group("drums").fx("Drum Buss", {drive: "<0 20>"}).send("verb", "<-30 -12>")
master.mix({vol: "<0 -3>"})

kick: s("bd*4").group("drums")
pad:  note("<c3 eb3>").s("sawtooth").release(0.3).send("verb", -6)
在 /TuttiCode 中打开

这些轨道没有自己的片段,所以“在 TuttiDAW 中打开”会把它们的自动化写进编排视图:写在返回轨道、drums 编组和程序的编组(master)上,在声部片段覆盖的范围内每个循环一份。把片段拉长后再求值一次,自动化会跟着延伸。代码写下的点归代码所有——手动编辑其中一个点,那条总线、编组或 master 就会与代码分离(“重新关联”可以让代码重新生效)。你在这个范围之前或之后画的点归你所有,代码从不改动它们。

不能变化的东西

  • 静态设置只接受常量:例如 Ensemble 声部的 voice 或滤波器类型。在那里写模式会报错,并列出可以变化的参数。
  • 用名称模式指定设备本身(.fx("<Reverb Delay>"))是错误:一个声部只有一条效果链。

在工作室里

包络归代码所有,和声部的其他值一样:每次求值都会重写它,设备显示的是模式的第一个值。ramp 和 env 会变成带曲线的真实断点,可以像任何包络一样编辑。和声部片段一样长的包络随片段循环;更长或更短的是带自己循环的非关联片段包络,.once() 的则是关闭了循环的非关联包络。手动编辑这条包络会让声部与代码分离(“重新关联”可以让代码重新生效)。一条包络最多 1024 个点;变化得更频繁的模式会改在更粗的网格上保持,并给出警告。