我有一个带有不同区域的3d空间,每个区域都有自己的声音。我的目标是当用户从一个区域移动到另一个区域时,实现平滑的音频过渡,基本上在音轨之间进行淡入淡出。 当用户改变主意并突然返回到刚刚离开的区域时,我也希望能够优雅地处理这种情况,这意味着取消新的音频过渡并逐渐恢复为先前的状态。
为此,我使用web audio api,尤其是linearRampToValueAtTime和cancelScheduledValues来定义淡入/淡出功能:
const fadeIn = (sound, time = 4, gain = 1.0) => {
sound.gainNode.gain.cancelScheduledValues(sound.context.currentTime)
!sound.isPlaying && sound.play()
sound.gainNode.gain.linearRampToValueAtTime(gain, sound.context.currentTime + time)
}
const fadeOut = (sound, time = 4, gain = 0.0) => {
sound.gainNode.gain.cancelScheduledValues(sound.context.currentTime)
sound.gainNode.gain.linearRampToValueAtTime(gain, sound.context.currentTime + time)
}
我仅在一种声音上对此进行测试,按下键“ I”触发淡入,按下键“ O”触发淡出:
document.addEventListener("keyup", e => {
switch (e.keyCode) {
// I key
case 73:
fadeIn(mySound)
break
// O key
case 79:
fadeOut(mySound)
break
})
我得到不一致的结果。有时,音频会正确淡入,而另一些时候,它会在fadeIn中突然开始或在fadeOut中切入。过渡未完成时,似乎调用 cancelScheduledValues 会导致行为不稳定。我希望即使在fadingIn尚未完成时触发fadeOut时,它也能平稳工作,反之亦然。我也尝试过使用setTimeout来延迟linearRamps,例如
setTimeout(() => sound.gainNode.gain.linearRampToValueAtTime(gain, sound.context.currentTime + time), 0.1)
,但结果同样错误。 我使用API的方式有误吗?有什么建议吗?
答案 0 :(得分:2)
我认为这里正在发生的事情是,例如,您正在逐渐消失,还没有完成爬坡。然后,您需要淡出并取消事件,包括未完成的淡入斜坡。然后淡入渐变消失了,时间轴值又恢复为上一个事件的值。
因此,正如HankMoody建议的那样,请使用import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
def hmac_sha256(String secretKey, String data) {
try {
Mac mac = Mac.getInstance("HmacSHA256")
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256")
mac.init(secretKeySpec)
return mac.doFinal(data.getBytes())
} catch (InvalidKeyException e) {
throw new RuntimeException("Invalid key exception while converting to HMac SHA256")
}
def x = hmac_sha256("secret", "my-data").encodeBase64().toString();
来解决此问题。但是,AFAIK只有Chrome具有此功能。
为便于携带,我认为您要做的是计算要取消时斜坡的位置。假设值为cancelAndHoldAtTime
。然后做
v
其中setValueAtTime(v, context.currentTime);
cancelScheduledValues(context.currentTime + eps);
是eps
附近的一个较小值,或者更大。