基于网络音频分析器API,我正在创建一个基于实时频谱绘制图像的音频动画(就像移动到声音频率的经典条形图形,除了它不是条形图绘制但更复杂的东西)。
它工作正常,我唯一的问题是我无法在精确的时间停止图像。 当我想让它停止时让我们说5秒钟,然后有时它停在5.000021,或5.000013,或5.0000098,...... 问题是频谱(以及基于此频谱的图像)在5.000021,或5.000013或5.0000098处不相同,...... 这意味着当用户想要看到对应于5s的图像时,每次他看到略微不同的图像,并且我希望只有一个图像对应于5s(通常图像在每次尝试时只是略有不同,但是有时差异非常大。)
以下是我的代码摘录:
var ctx = new AudioContext();
var soundmp3 = document.getElementById('soundmp3');
soundmp3.src = URL.createObjectURL(this.files[0]);
var audioSrc = ctx.createMediaElementSource(soundmp3);
var analyser = ctx.createAnalyser();
analyser.fftSize = 2048;
analyser.smoothingTimeConstant = 0.95;
audioSrc.connect(analyser);
audioSrc.connect(ctx.destination);
var frequencyData = new Uint8Array(analyser.frequencyBinCount);
function renderFrame() {
if(framespaused) return;
drawoneframe();
requestAnimationFrame(renderFrame);
};
function drawoneframe(){
analyser.getByteFrequencyData(frequencyData);
// drawing of my image ...
};
function gotomp3(timevalue){
soundmp3.pause();
newtime = timevalue;
backtime = newtime - 0.2000;
soundmp3.currentTime = backtime;
soundmp3.play();
function boucle(){
if(soundmp3.currentTime >= timevalue){
if(Math.abs(soundmp3.currentTime-newtime) <= 0.0001){
drawoneframe();
soundmp3.pause();
soundmp3.currentTime = timeatgetfrequency;
return;
} else {
soundmp3.pause();
soundmp3.currentTime = backtime;
soundmp3.play();
};
}
setTimeout(boucle, 1);
};
boucle();
};
document.getElementById("fieldtime").onkeydown = function (event) {if (event.which == 13 || event.keyCode == 13) {
gotomp3(document.getElementById("fieldtime").value);
return false;
}
return true;
};
代码说明:如果用户在“fieldtime”(= newtime)输入一个值并按下enter键,那么我先返回0.2秒,开始播放并在currentTime非常接近newtime时停止(我必须请先返回,因为当我直接进入newtime并在之后立即停止时,analyser.getByteFrequencyData在newtime时还没有值。使用boucle()我设法让它在非常精确的时间停止:如果newtime = 5,那么drawoneframe();被称为5.000xx,但问题是,每次用户输入5作为新时间时,显示的图像略有不同。
所以我的问题是:有人知道如何在每次用户输入新时间的同时实现这一目标,图像将完全相同吗?
我不太清楚soundmp3.currentTime在哪些时候更新了?对于44.1kHz的采样率,我猜它类似于每0.0227ms,但这是否意味着它正好更新为0,0.0227ms,0.0454ms,......或者只是大约? 我考虑过平滑分析仪的结果,因此对于小的时间变化,变化较小。将analyser.smoothingTimeConstant设置为接近1的值是不够的。但也许有另一种方法可以做到这一点。 我不需要高精度的结果,我只是想如果用户想要看到对应于x秒的图像,那么每次进入x秒时,他都会看到完全相同的图像。
非常感谢您的帮助。 米雷耶