当我使用以下代码淡入文件时,它并不像我期望的那样工作。我希望在5秒内从0逐渐淡入1,而不是在播放文件的5秒钟内突然变化,其中增益立即从0变为1.我不理解什么?
soundObj.play = function() {
playSound.buffer = soundObj.soundToPlay;
playSound.connect(gainNode);
gainNode.gain.value = 0;
gainNode.gain.exponentialRampToValueAtTime(1, audioContext.currentTime + 5);
gainNode.connect(audioContext.destination);
playSound.start(audioContext.currentTime);
}
更新/编辑
我将上面的代码更改为以下代码似乎有效,现在我正在研究原因。我添加了一些评论。主要询问是否需要添加setValueAtTime方法,以及gain.value属性默认值是否需要非零值。
soundObj.play = function() {
playSound.buffer = soundObj.soundToPlay;
playSound.connect(gainNode);
gainNode.gain.value = 0.001; // If set to 0 it doesn't fade in
gainNode.gain.setValueAtTime(gainNode.gain.value, audioContext.currentTime); // Is this needed to have the other RampToValue methods work ?
gainNode.gain.exponentialRampToValueAtTime(1, audioContext.currentTime + 7);
gainNode.connect(audioContext.destination);
playSound.start(audioContext.currentTime);
}
答案 0 :(得分:4)
exponentialRampToValueAtTime
需要非零正值。这不仅仅是一个网络音频的事情,而只是一个数学事物。
实际上没有办法以指数方式增加0值。
这是Chrome使用的算法的粗略版本(在JS中重写):
// start value
var value1 = 0.1;
// target value
var value2 = 1;
// start time (in seconds)
var time1 = 0;
// end time (in seconds)
var time2 = 2;
// duration
var deltaTime = time2 - time1;
// AudioContext sample rate
var sampleRate = 44100;
// total number of samples
var numSampleFrames = deltaTime * sampleRate;
// time incrementer
var sampleFrameTimeIncr = 1 / sampleRate;
// current time (in seconds)
var currentTime = 0;
// per-sample multiplier
var multiplier = Math.pow( value2 / value1, 1 / numSampleFrames );
// output gain values
var values = new Array( numSampleFrames );
// set up first value
var value = value1 * Math.pow( value2 / value1, ( ( currentTime - time1 ) * sampleRate ) / numSampleFrames );
for ( var i = 0; i < numSampleFrames; ++i ) {
values[ i ] = value;
value *= multiplier;
currentTime += sampleFrameTimeIncr;
}
如果将value1
更改为零,您将看到输出数组基本上已满NaN
。但是,Chrome还添加了一些额外的代码,以便通过特殊的大小写实例(<= 0
)来保护您,使您实际上不会获得NaN
的增益值。< / p>
如果这些都没有意义,那就让我这样说吧。为了以指数方式增长值,您基本上需要一个如下所示的循环:
for ( var i = 0; i < length; ++i ) {
values[ i ] = value;
value *= multiplier;
}
但如果您的初始值为0
,那么0
乘以任何其他数字始终为0
。
哦,如果您对此感兴趣(并且可以阅读C ++),请点击此链接指向Chrome使用的代码:https://chromium.googlesource.com/chromium/blink/+/master/Source/modules/webaudio/AudioParamTimeline.cpp
相关内容在第316行。
修改的
以Chrome为中心的解释道歉。但是,无法以指数方式增加零值的基本数学概念将适用于任何实现。