当尝试实现ADSR封装时,它很容易实现ADS攻击,衰减和延迟,因为所有这些值的时序同时是已知的。但是,如果尝试实现此信封的发布部分,我会遇到麻烦。
问题是我已经注意到并提前注意了预定的事件。但是,AudioParams.linearRampToValueAtTime只需要两个参数,即斜坡应该结束的时间和它应该结束的值。
然后如何产生一个在某个时间开始的斜坡?
/**
* @param attack {int}
* @param decay {int}
* @param sustain {number} 0-100 percentage of overall level
* @param release {int} time for volume to reach 0
*/
function ADSR(attack, decay, sustain, release) {
this.attack = attack;
this.decay = decay;
this.sustain = sustain;
this.release = release;
function applyTo(audioParam, time) {
audioParam.linearRampToValueAtTime(1, time+attack);
audioParam.linearRampToValueAtTime(this.sustain/100, time+attack+decay);
}
this.applyTo = applyTo;
function applyRelease(audioParam, time, audioNode) {
// here I want to apply the release starting at the time given
// ending at time + this.time
}
return time;
}
答案 0 :(得分:2)
根据spec事件按顺序计算,因此如果您在setValueAtTime
之前安排了rampToValueAtTime
,则会在此之后计算出渐变:
audioParam.setValueAtTime(audioParam.value, time);
audioParam.linearRampToValueAtTime(0, time+this.time);
如果您正在寻找能够在保持当前值的同时减速的事情(斜坡的时间取决于当前值与给定目标值之间的差异),我建议您使用setTargetAtTime
系统。这应该是有用的,因为spec提及它在您的情况下有用:
在给定时间以指定时间常数的速率开始以指数方式接近目标值。在其他用途中,这对于实现"衰变"和"发布" ADSR包络的一部分。
这是使用timeConstant计算的,它定义了延迟到1 - 1/e (around 63.2%)
所需的时间。使用它像
audioParam.setTargetAtTime(<target_value>, <start_Time>, <timeConstant>);
时间常数越高,转换越慢。我建议您使用该值来查看适合您情况的内容。