简体   繁体   English

Web Audio API AnalyserNode中的可能错误

[英]Possible bug in Web Audio API AnalyserNode

I was playing around with Web Audio API and maybe found a bug in the AnalyserNode. 我在玩Web Audio API,也许在AnalyserNode中发现了一个错误。 Let's say I have two sine oscillators playing at different frequencies, 200 Hz and 8000 Hz respectively. 假设我有两个正弦振荡器,分别以200 Hz和8000 Hz的不同频率运行。 Using two different AnalyserNode(s) I extract the non-zero frequency data from the two oscillators, which are the following (from chrome console): 通过使用两个不同的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

Now if I change the frequency value of the first oscillator to 8000 Hz (the same of the second oscillator) and extract again the non-zero frequency data I expect to obtain non zero values approximately in the same Bins of the second oscillator (say in the 300-400 range), but strangely there are non zero values also in the Bins in range 0-50 (as when we extracted frequency data using a 200 Hz frequency). 现在,如果我将第一个振荡器的频率值更改为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

Is this the expected behavior or a bug? 这是预期的行为还是错误? It seems not correct to me. 对我来说似乎不正确。 I am also not sure if this propagates also when analyzing a standard audio file using for example a requestAnimationFrame loop. 我也不确定在使用例如requestAnimationFrame循环分析标准音频文件时,是否还会传播。 Below the code of the full example. 下面是完整示例的代码。

NB: to extract the frequency data is required to wait a bit before the analyser has finished the Fast Fourier Transform algorithm and the frequency data is available, thus I've used 2 timeOut functions, one for the first extraction of frequency data from osc1 and osc2 and the second to extract again frequency data from osc1 after the oscillator frequency has changed to 8000 Hz). 注意:要提取频率数据,需要等待一段时间,直到分析仪完成快速傅立叶变换算法并且频率数据可用为止,因此我使用了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("");
}

This is expected. 这是预期的。 According to the spec , successive calls to extract the frequency data combines the data from the current call with a history of the data from previous calls. 根据规范 ,连续的提取频率数据的调用将当前调用中的数据与以前调用中的数据历史结合起来。 If we want to see the frequency data only from the current time, set smoothingTimeConstant to 0. 如果我们只想查看当前时间的频率数据,请将smoothingTimeConstant设置为0。

smoothingTimeConstant on Mozilla Developer Network Mozilla开发人员网络上的smoothingTimeConstant

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

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