I am having problems with the 'windowing', as it's called, of pitch-shifted grains of sounds using the Web Audio API. When I play the sound, I successfully set the initial gain to 0, using setValueAtTime, and successfully fade the sound in using linearRampToValueAtTime. However, I am not successful in scheduling a fade-out to occur slightly before the sound ends. It may be because the sound is pitch-shifted, although in the code below, I believe I have set the parameters correctly. Though maybe the final parameter in setTargetAtTime is not suitable because I don't fully understand that parameter, despite having read Chris's remarks on the matter. How does one successfully schedule a fade-out when the sound is pitch-shifted, using setTargetAtTime? Below is my code. You can see the piece itself at https://vispo.com/animisms/enigman2/2022
source.buffer = audioBuffer;
source.connect(this.GrainObjectGain);
this.GrainObjectGain.connect(app.mainGain);
source.addEventListener('ended', this.soundEnded);
//------------------------------------------------------------------------
// Now we do the 'windowing', ie, when we play it, we fade it in,
// and we set it to fade out at the end of play. The fade duration
// in seconds is a maximum of 10 milliseconds and
// a minimum of 10% of the duration of the sound. This helps
// eliminate pops.
source.playbackRate.value = this.playbackRate;
var fadeDurationInSeconds = Math.min(0.01,0.1*duration*this.playbackRate);
this.GrainObjectGain.gain.setValueAtTime(0, app.audioContext.currentTime);
this.GrainObjectGain.gain.linearRampToValueAtTime(app.constantGrainGain, app.audioContext.currentTime+fadeDurationInSeconds);
this.GrainObjectGain.gain.setTargetAtTime(0, app.audioContext.currentTime+duration*this.playbackRate-fadeDurationInSeconds, fadeDurationInSeconds);
source.start(when, offset, duration);
Given your comment below I guess you want to schedule the fade out
fadeDurationInSecondsbefore the sound ends.Since you change
playbackRateyou need to divide the originaldurationby thatplaybackRateto get the actual duration.Changing your
setTargetAtTime()call as follows should schedule the fade out at the desired point in time.Please not that
setTargetAtTime()actually never reaches thetarget. At least in theory. It comes reasonably close though after some time. But that time is longer as thetimeConstant.The relevant text from the spec can be found here: https://webaudio.github.io/web-audio-api/#dom-audioparam-settargetattime
The
timeConstantparameter roughly defines the time it takes to reach 2/3 of the desired signal attenuation.It's mentioned here: https://webaudio.github.io/web-audio-api/#dom-audioparam-settargetattime-timeconstant