繁体   English   中英

Web Audio API AnalyserNode中的可能错误

[英]Possible bug in Web Audio API AnalyserNode

我在玩Web Audio API,也许在AnalyserNode中发现了一个错误。 假设我有两个正弦振荡器,分别以200 Hz和8000 Hz的不同频率运行。 通过使用两个不同的AnalyserNode,我从两个振荡器中提取了非零频率数据,这些数据如下(从chrome控制台):

OSC1 (200 Hz)
Bin 0   value 1
Bin 1   value 3
Bin 2   value 9
Bin 3   value 18
Bin 4   value 30
Bin 5   value 43
Bin 6   value 36
Bin 7   value 159
Bin 8   value 236
Bin 9   value 255
Bin 10  value 255
Bin 11  value 212
Bin 12  value 86
Bin 13  value 46
Bin 14  value 36
Bin 15  value 21
Bin 16  value 8

OSC2 (8000 Hz)
Bin 364     value 6
Bin 365     value 18
Bin 366     value 32
Bin 367     value 46
Bin 368     value 52
Bin 369     value 126
Bin 370     value 224
Bin 371     value 255
Bin 372     value 255
Bin 373     value 226
Bin 374     value 132
Bin 375     value 51
Bin 376     value 47
Bin 377     value 33
Bin 378     value 19
Bin 379     value 7

现在,如果我将第一个振荡器的频率值更改为8000 Hz(与第二个振荡器相同),并再次提取非零频率数据,我希望在第二个振荡器的相同Bin中获得近似于零的非零值(例如300-400范围内),但奇怪的是,在Bins中0-50范围内也有非零值(就像我们使用200 Hz频率提取频率数据时一样)。

OSC1 (8000 Hz)
Bin 2   value 2
Bin 3   value 11
Bin 4   value 23
Bin 5   value 36
Bin 6   value 29
Bin 7   value 152
Bin 8   value 229
Bin 9   value 255
Bin 10  value 248
Bin 11  value 205
Bin 12  value 79
Bin 13  value 38
Bin 14  value 29
Bin 15  value 14
Bin 16  value 1
Bin 364     value 7
Bin 365     value 19
Bin 366     value 33
Bin 367     value 47
Bin 368     value 50
Bin 369     value 137
Bin 370     value 228
Bin 371     value 255
Bin 372     value 255
Bin 373     value 222
Bin 374     value 121
Bin 375     value 52
Bin 376     value 45
Bin 377     value 31
Bin 378     value 18
Bin 379     value 5

这是预期的行为还是错误? 对我来说似乎不正确。 我也不确定在使用例如requestAnimationFrame循环分析标准音频文件时,是否还会传播。 下面是完整示例的代码。

注意:要提取频率数据,需要等待一段时间,直到分析仪完成快速傅立叶变换算法并且频率数据可用为止,因此我使用了2个timeOut函数,其中一个用于从osc1和osc2,第二个在振荡器频率更改为8000 Hz之后再次从osc1提取频率数据。

var AudioContext = window.AudioContext || window.webkitAudioContext;
var ctx = new AudioContext();

// first oscillator (200 Hz)
var osc1 = ctx.createOscillator();
osc1.frequency.value = 200;

var analyser1 = ctx.createAnalyser();

var gain1 = ctx.createGain();
gain1.gain.value = 0;

osc1.connect(analyser1);
analyser1.connect(gain1);
gain1.connect(ctx.destination);



// second oscillator (8000 Hz)
var osc2 = ctx.createOscillator();
osc2.frequency.value = 8000;

var analyser2 = ctx.createAnalyser();

var gain2 = ctx.createGain();
gain2.gain.value = 0;

osc2.connect(analyser2);
analyser2.connect(gain2);
gain2.connect(ctx.destination);


// start oscillators
osc1.start();
osc2.start();


// get frequency data
var freqData1 = new Uint8Array(analyser1.frequencyBinCount);
var freqData2 = new Uint8Array(analyser2.frequencyBinCount);


setTimeout(function() {
    analyser1.getByteFrequencyData(freqData1);
    analyser2.getByteFrequencyData(freqData2);
    console.log("OSC1 (200 Hz)");
    printNonZeroFreqData(freqData1);
    console.log("OSC2 (8000 Hz)");
    printNonZeroFreqData(freqData2);


    // change frequency of osc1 to 8000 Hz 
    osc1.frequency.value = 8000;

    // wait a bit, then extract again frequency data from osc1
    setTimeout(function() {
        freqData1 = new Uint8Array(analyser1.frequencyBinCount);
        analyser1.getByteFrequencyData(freqData1);
        console.log("OSC1 (8000 Hz)");
        printNonZeroFreqData(freqData1);        
    }, 500);


}, 500);





// print non zero frequency values
function printNonZeroFreqData(arr) {
    for (var i = 0; i < arr.length; ++i) {
        if (arr[i] != 0) {
            console.log("Bin " + i, "\tvalue " + arr[i]);
        }
    }
    console.log("");
}

这是预期的。 根据规范 ,连续的提取频率数据的调用将当前调用中的数据与以前调用中的数据历史结合起来。 如果我们只想查看当前时间的频率数据,请将smoothingTimeConstant设置为0。

Mozilla开发人员网络上的smoothingTimeConstant

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM