如何使用各种rampToValueAtTime方法
How to use the various rampToValueAtTime methods
当我使用以下代码淡入文件时,它无法按预期工作。我希望在 0 秒内从 5 秒逐渐淡入 1,相反,我在播放文件五秒后突然发生变化,增益立即从 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);
}
非零正值对于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
的增益值。
如果这些都没有意义,让我这样说吧。为了以指数方式增长一个值,你基本上需要一个如下所示的循环:
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 为中心的解释,我们深表歉意。但是,无法以指数方式增长零值的基本数学概念在任何实现中都成立。
相关文章:
- 没有找到相关文章