Вопрос

When trying to implement an ADSR envelop its easy to implement ADS Attack, Decay and Sustain as the timing of all those values are known at the same time. However if attempting to implement the Release part of this envelop I'm running into trouble.

The problem is that I've note on and note off events which are scheduled ahead of time. However AudioParams.linearRampToValueAtTime however only takes two arguments the time that the ramp should end and the value that it should end at.

How does one then produce a ramp that begins at a certain time?

/**
 * @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;
}
Это было полезно?

Решение

According to the spec events are calculated in order, so if you have a setValueAtTime scheduled before a rampToValueAtTime the ramp will get calculated after that:

audioParam.setValueAtTime(audioParam.value, time);
audioParam.linearRampToValueAtTime(0, time+this.time);

If you are looking for something that ramps while keeping the current value in mind (the time to ramp depends on the difference between the value right now and the given target value), I recommend you to use the setTargetAtTime system. This should be usefull as the spec mentions it is for example useful in your situation:

Start exponentially approaching the target value at the given time with a rate having the given time constant. Among other uses, this is useful for implementing the "decay" and "release" portions of an ADSR envelope.

This calculates with a timeConstant, which defines how much time it should take to ramp to 1 - 1/e (around 63.2%).Use it like

audioParam.setTargetAtTime(<target_value>, <start_Time>, <timeConstant>);

The higher the time constant, the slower the transition is. I recommend you play around with the value to see what fits for your situation.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top