Анализатор веб-аудио javascript: getByteFrequencyData в точное время?

Основываясь на API веб-аудиоанализатора, я создаю аудио-анимацию, которая рисует изображения на основе частотного спектра в реальном времени (например, классическая линейная графика, которая перемещается на частоту звука, за исключением того, что рисуются не полосы, а что-то более сложный).

Это работает нормально, моя единственная проблема в том, что я не могу остановить изображение в точное время. Когда я хочу, чтобы он остановился, скажем, на 5 секунд, то иногда он останавливается на 5.000021, или 5.000013, или 5.0000098, ... и проблема в том, что частотный спектр (и поэтому мое изображение, основанное на этом частотном спектре) не то же самое в 5.000021, или 5.000013, или 5.0000098, ... Это означает, что пользователь, когда он хочет видеть изображение, соответствующее 5 с, каждый раз, когда он видит немного другое изображение, и я хотел бы, чтобы только одно изображение соответствовало до 5 с (часто изображение только слегка отличается при каждой попытке, но иногда различия довольно велики).

Вот выдержки из моего кода:

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 как новое время, отображаемое изображение немного отличается.

Итак, мой вопрос: есть ли у кого-нибудь идея, как мне добиться того, чтобы каждый раз, когда пользователь заходил в то же время, что и newtime, изображение было точно таким же?

Я не совсем знаю, в какое время обновляется soundmp3.currentTime? С частотой дискретизации 44,1 кГц, я думаю, что это примерно каждые 0,0227 мс, но означает ли это, что он обновляется точно на 0, 0,0227 мс, 0,0454 мс,... или только приблизительно? Я думал о сглаживании результатов анализатора, чтобы было меньше вариаций для небольших вариаций времени. Недопустимо задавать Analyser.smoothingTimeConstant значение, близкое к 1. Но, возможно, есть другой способ сделать это. Мне не нужны результаты с высокой точностью, я просто хотел бы, чтобы, если пользователь хочет видеть изображение, соответствующее x секундам, то каждый раз, когда он вводит x секунд, он видит одно и то же изображение.

Большое спасибо за любую помощь. Мирей

0 ответов

Другие вопросы по тегам