根据参考 csound 手册,在编写响应 MIDI 的乐器时应该使用xtratim
(或隐式使用它的操作码,例如),因为事先不知道键/音符的持续时间(对于现场表演)。madsr
但是,我还在一个外部示例中注意到,可以从乐器代码中覆盖 p3(乐谱音符长度)。那么,这样做和使用之间有什么区别xtratim
吗?
是的,当音符关闭时,具有发布段的 xtratim 和 -r 操作码将触发额外的发布时间。p3 将只是“开启”时间的持续时间值。
例如,如果您运行以下命令:
instr S1
p3 = 2
asig = oscili(0.25, 440)
asig *= linsegr(1, .1, 1, 4, 0)
out(asig, asig)
endin
schedule("S1", 0, 0.1)
通常,应谨慎使用覆盖 p3,但它适用于某些情况,例如确保为仪器提供最少的时间。xtratim 或 -r 操作码的发布时间可能更适用于大多数用例。
由于xtratim
获得了 i-arg 额外的时间,我希望改变 p3 会更灵活,但实际上并非如此......
对于初学者,p3 被视为 i-var,即它只能在初始传递时分配,所以类似于
instr 1
if p3 < 9 then
p3 = p3 + 1 ; runs only once
printk 0.1, p3
endif
endin
如果从得分中调用,则只会运行三秒钟
i1 0 2
这是意料之中的事。另一方面,调用reinit
[re]run 初始化阶段的以下 hack 确实不止一次更新 p3,但这对音符播放时间的影响为零,即只有第一个(“真正的 init”)改变了实际的音符持续时间... perf-time 重新初始化,同时更改从乐器读取的 p3,对音符播放持续时间没有任何影响,即
top:
p3 = p3 + 1
printk 0.1, p3
if p3 < 9 then
reinit top
endif
仍然以相同的分数播放 3 秒(即使我确保 Csound 运行时间足够长),即:
i1 0 2
e 10
尽管 printk 确实将 p3 显示为使用后一种仪器达到值 9...
至于xtratim
它根本不会改变 p3,正如 Steven' Yi 的回答正确指出的那样,“额外时间”是在此之外实施的。
查看 xtratim 的源代码,实际上可以通过多次调用 xtratim 来延长“额外时间”,并不断增加值,但不能缩短它......
int32_t xtratim(CSOUND *csound, XTRADUR *p)
{
IGN(csound);
int32_t *xtra = &(p->h.insdshead->xtratim);
int32_t tim = (int32_t)(*p->extradur * p->h.insdshead->ekr);
if (*xtra < tim) /* gab-a5 revised */
*xtra = tim;
return OK;
}
有了这些信息,我尝试了
ixtr = 0
top:
ixtr += 1
xtratim ixtr
print ixtr
if ixtr < 8 then
reinit top
endif
你瞧,后面的 hack 确实有效,即后面的代码实际上使用之前的分数将乐器/音符的播放时间延长到 10 秒。因此,与破解 p3 不同,可以在演奏时从仪器内部以这种方式以编程方式扩展音符,随心所欲地扩展音符。
对于那些好奇的人,xtratim
即使在发布已被断言之后调用,甚至在播放(实际发布)时间(正确地)生效,即即使从“发布段”,例如
xtratim 1
kflag release
kdone init 0
if (kflag == 1) && (kdone == 0) then
kdone = 1
reinit more
more:
xtratim 4
endif
将额外提供 4 秒的播放时间。鉴于此,我不确定在 perf 期间忽略 p3 更新是错误还是“设计使然”。