如何使用各种rampToValueAtTime方法

时间:2014-11-18 08:46:16

标签: javascript asp.net-web-api html5-audio web-audio

当我使用以下代码淡入文件时,它并不像我期望的那样工作。我希望在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);
}

1 个答案:

答案 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为中心的解释道歉。但是,无法以指数方式增加零值的基本数学概念将适用于任何实现。

相关问题