gpt4 book ai didi

javascript - Web Audio API 使用 AnalyserNode 创建峰值计

转载 作者:行者123 更新时间:2023-11-30 07:13:13 28 4
gpt4 key购买 nike

实现 Peak Meter 的正确方法是什么?就像 Logic Pro 中的那些使用网络音频 API AnalyserNode

我知道AnalyserNode.getFloatFrequencyData()返回分贝值,但如何组合这些值以获得要在仪表中显示的值?您是否像下面的代码示例一样取最大值(其中 analyserData 来自 getFloatFrequencyData():

let peak = -Infinity;
for (let i = 0; i < analyserData.length; i++) {
const x = analyserData[i];
if (x > peak) {
peak = x;
}
}

检查仅取最大值的一些输出使得这看起来不是正确的方法。我错了吗?

或者,改用 ScriptProcessorNode 会更好吗?这种方法有何不同?

最佳答案

如果您在一帧中取 getFloatFrequencyData() 结果的最大值,那么您测量的是单个频率的音频功率(取其最强大)。您实际想要测量的是任何频率处的峰值——换句话说,您想要使用频率数据,但未处理的样本未被分成频率仓。

问题是您必须自己计算分贝功率。这是相当简单的算术:你取一些样本(一个或多个),对它们进行平方,然后取平均值。请注意,即使是“峰值”仪表也可能会进行平均 - 只是在更短的时间范围内。

这是一个完整的例子。 (警告:发出声音。)

document.getElementById('start').addEventListener('click', () => {
const context = new(window.AudioContext || window.webkitAudioContext)();

const oscillator = context.createOscillator();
oscillator.type = 'square';
oscillator.frequency.value = 440;
oscillator.start();

const gain1 = context.createGain();

const analyser = context.createAnalyser();

// Reduce output level to not hurt your ears.
const gain2 = context.createGain();
gain2.gain.value = 0.01;

oscillator.connect(gain1);
gain1.connect(analyser);
analyser.connect(gain2);
gain2.connect(context.destination);

function displayNumber(id, value) {
const meter = document.getElementById(id + '-level');
const text = document.getElementById(id + '-level-text');
text.textContent = value.toFixed(2);
meter.value = isFinite(value) ? value : meter.min;
}

// Time domain samples are always provided with the count of
// fftSize even though there is no FFT involved.
// (Note that fftSize can only have particular values, not an
// arbitrary integer.)
analyser.fftSize = 2048;
const sampleBuffer = new Float32Array(analyser.fftSize);

function loop() {
// Vary power of input to analyser. Linear in amplitude, so
// nonlinear in dB power.
gain1.gain.value = 0.5 * (1 + Math.sin(Date.now() / 4e2));

analyser.getFloatTimeDomainData(sampleBuffer);

// Compute average power over the interval.
let sumOfSquares = 0;
for (let i = 0; i < sampleBuffer.length; i++) {
sumOfSquares += sampleBuffer[i] ** 2;
}
const avgPowerDecibels = 10 * Math.log10(sumOfSquares / sampleBuffer.length);

// Compute peak instantaneous power over the interval.
let peakInstantaneousPower = 0;
for (let i = 0; i < sampleBuffer.length; i++) {
const power = sampleBuffer[i] ** 2;
peakInstantaneousPower = Math.max(power, peakInstantaneousPower);
}
const peakInstantaneousPowerDecibels = 10 * Math.log10(peakInstantaneousPower);

// Note that you should then add or subtract as appropriate to
// get the _reference level_ suitable for your application.

// Display value.
displayNumber('avg', avgPowerDecibels);
displayNumber('inst', peakInstantaneousPowerDecibels);

requestAnimationFrame(loop);
}
loop();
});
<button id="start">Start</button>

<p>
Short average
<meter id="avg-level" min="-100" max="10" value="-100"></meter>
<span id="avg-level-text">—</span> dB
</p>

<p>
Instantaneous
<meter id="inst-level" min="-100" max="10" value="-100"></meter>
<span id="inst-level-text">—</span> dB
</p>

关于javascript - Web Audio API 使用 AnalyserNode 创建峰值计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44360301/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com