我目前可以使用JavaScript Web Audio API播放音轨。在播放此曲目时,我可以提取FFT频谱数据,峰值,RMS值等。
但是,出于我的应用目的,我需要能够在开始播放之前从轨道中提取所有这些数据。
有没有办法使用Web Audio API执行此操作。如果没有,这怎么可能呢?
我尝试使用以下代码实现此目的,但它为每个框架返回了完全相同的值':
当用户选择文件时加载音频:
var fileChooser = document.getElementById("chooseAudio");
var audio = null;
var file = fileChooser.files[0];
var reader = new FileReader();
reader.onload = function(e) {
audio = new Audio(reader.result);
}
reader.readAsDataURL(file);
加载音频后:
var FPS = 60;
var INCREMENT = 1 / FPS;
var FFT_SIZE = 256;
var SMOOTHING = 0.7;
var duration = null;
var length = null;
var width = null;
var time = null;
var analyser = null;
var data = null;
var index = null;
function analyse() {
duration = audio.duration / APR;
length = Math.ceil(duration * FPS);
width = 4;
time = 0.0;
data = array(length, width);
index = 0;
var context = new AudioContext();
analyser = context.createAnalyser();
analyser.fftSize = FFT_SIZE;
analyser.smoothingTimeConstant = SMOOTHING;
var source = context.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(context.destination);
audio.play();
while (index < length) {
audio.currentTime = time;
frame = getFrame();
data[index] = frame;
time += INCREMENT;
index++;
}
audio.pause();
audio.currentTime = 0;
}
function getFrame() {
var rawFreq = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(rawFreq);
var rawTimeDom = new Uint8Array(analyser.fftSize);
analyser.getByteTimeDomainData(rawTimeDom);
var frame = [];
frame.push(peak(rawTimeDom), rms(rawTimeDom), low(rawFreq), high(rawFreq));
return frame;
}
data
的输出:
[
[128, 128, 100.2, 68.3],
[128, 128, 100.2, 68.3],
...
[128, 128, 100.2, 68.3]
]
此外,我应该澄清一下,我尝试每秒60次采样音频的原因是因为我需要稍后以相同的速率显示音频数据。
答案 0 :(得分:1)
您可以使用OfflineAudioContext
代替AudioContext
来预处理数据,而不是实时运行音频管道。
OfflineAudioContext不会将音频呈现给设备硬件;相反,它会尽可能快地生成它,并将结果输出到AudioBuffer。
在使用普通上下文播放音频之前,您可以在离线环境中进行处理!
答案 1 :(得分:0)
如果您确实拥有一组文件并需要预先处理它们,请使用decodeAudioData
从每个文件中获取音频数据。使用OfflineAudioContext
代替AudioContext
来获取分析仪数据。但是,由于离线上下文的运行速度可能比实时更快,因此在调用getByteTimeDomainData
时需要注意。这里最好使用suspend
和resume
,您可以在getFrame
中致电suspend
。
但是,根据getFrame
所做的事情(获取音频样本),您可能最好使用ScriptProcessorNode
或AudioWorklet
来获取您所需的时域数据。正在寻找。这些适用于AudioContext
或OfflineAudioContext
。