2013-03-28 5 views
3

Я работаю с веб-аудио api и requestAnimationFrame для визуализации аудиовхода с микрофона. Я могу успешно визуализировать частотные данные во временной области, но проблема в том, что, поскольку веб-аудио api вычисляет время в секундах, каждую секунду мой интерфейс изменяется в зависимости от того, что такое вход.обработка в реальном времени веб-аудио api

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

Я использую следующий код (взял из примеров here):

MicrophoneSample.prototype.visualize = function() { 
    this.canvas.width = this.WIDTH; 
    this.canvas.height = this.HEIGHT; 
    var drawContext = this.canvas.getContext('2d'); 

    var times = new Uint8Array(this.analyser.frequencyBinCount); 
    this.analyser.getByteTimeDomainData(times); 
    for (var i = 0; i < times.length; i++) { 
    var value = times[i]; 
    var percent = value/256; 
    var height = this.HEIGHT * percent; 
    var offset = this.HEIGHT - height - 1; 
    var barWidth = this.WIDTH/times.length; 
    drawContext.fillStyle = 'purple'; 
    drawContext.fillRect(i * barWidth, offset, 1, 1); 

    } 
    requestAnimFrame(this.visualize.bind(this)); 

} 
+0

Rq: изменение размера холста/получение контекста на каждом вызове является излишним: сделайте это один раз и сохраните ctx. Разве нет необходимости подключать ваш источник звука к анализатору, чтобы получить частоты? – GameAlchemist

+0

Вход уже подключен к анализатору, и я также могу получить значения формы волны или другие звуковые свойства. Главная проблема заключается в том, как сделать визуализацию их резидентом? – user2039789

ответ

2

getByteTimeDomainData не дает вам частотную информацию. Это значения формы сигнала временной области в реальном времени, также известные как значения амплитуды. Если вы хотите визуализировать их со временем, добавьте значения в массив и нарисуйте это. Если вам нужны реальные значения частоты, используйте getByteFrequencyData.

+0

Если getByteTimeDomainData позволяет создать форму сигнала, которая также полезна. Эти примеры уже визуализируют ввод, но, как я сказал каждую секунду, график исчезает. Как я могу заставить его оставаться там? – user2039789

+1

Как я уже сказал, нажимаем данные времени [i] в ​​другой массив, который вы храните в классе MicrophoneSample, и рисуете этот массив. – headchant

+0

что-то вроде этого: http://jsfiddle.net/ez6R6/1/ – headchant

2

ОП, вот какой-то псевдокод. FYI, это действительно не вопрос веб-аудио, больше вопрос анимации.

Храните переменную/поле в функции прототипа визуализатора, которая отслеживает, сколько секунд вы хотите отложить перерисовку вашего холста, сохранить отдельный счетчик, который будет увеличиваться каждый раз, когда запросAnimFrame (...) нарисован. Как только ваш счетчик достигнет вашей суммы задержки, затем перерисуйте холст.

Редактировать Теперь, когда я думаю об этом ... решение должно быть очень простым. Исправьте меня, если я ошибаюсь, но это грубое решение предполагает, что вы вызываете MicrophoneSample.visualize() из цикла анимации ... и, следовательно, код в нем выполняется каждую секунду. Я мог бы помочь, если вы разместите свой объектный код MicrophoneSample или, по крайней мере, цикл анимации.

/* NOTE! 
* 
*/ 
// Find a way to put these into your PARENT MicrophoneSample object 
var delay = 5; 
// Note that I am setting delayCount initially to zero - during the loop 
// the delayCount will actually get reset to 1 from thereafter (not 0)... 
// this gives us a way to initially draw your visualization on the first frame. 
var delayCount = 0; 

// Pull var times out so it doesn't get calculated each time. 
var times = new Uint8Array(MicrophoneSample.analyser.frequencyBinCount); 

// Same goes for the canvas... 
// I would set these values inside of the PARENT MicrophoneSample object 
MicrophoneSample.canvas.width = this.WIDTH; 
MicrophoneSample.canvas.height = this.HEIGHT; 

// you only need to establish the drawing context once. Do it in the PARENT 
// MicrophoneSample object 
var drawContext = this.canvas.getContext('2d'); 

MicrophoneSample.prototype.visualize = function() { 

     /* 
     * NOTE! 
     */ 
     // Here's the juicy meat & potatoes: 
     // only if the delayCount reaches the delay amount, should you UPDATE THE 
     // TIME DOMAIN DATA ARRAY (times) 
     // if your loop runs every second, then delayCount increments each second 
     // and after 5 seconds will reach your designated delay amount and update your 
     // times array. 

     if(delayCount == 0 || delayCount == delay) { 
      this.analyser.getByteTimeDomainData(times); 

      // Now, it would be redundant (and totally noob-programmer of you) to 
      // redraw the same visualization onto the canvas 5 times in a row, so 
      // only draw the visualization after the first pass through the loop and then 
      // every 5th pass after that :] 
      for (var i = 0; i < times.length; i++) { 
       var value = times[i]; 
       var percent = value/256; 
       var height = this.HEIGHT * percent; 
       var offset = this.HEIGHT - height - 1; 
       var barWidth = this.WIDTH/times.length; 
       drawContext.fillStyle = 'purple'; 
       drawContext.fillRect(i * barWidth, offset, 1, 1); 
      } 

      // Note: 1, not 0! 
      delayCount = 1; 
     } 
     else { 
      delayCount++; 
     } 


     requestAnimFrame(this.visualize.bind(this)); 
} 

И просто имейте в виду, что я на самом деле ничего не проверял. Но это должно по крайней мере указывать на вас в правильном направлении.

+0

Я попытался реализовать решение, используя ваш псевдокод, но не добился успеха. Не знаю, из-за моих навыков программирования или ... Не могли бы вы написать код более подробно здесь или в личку? Спасибо, приятель :))) – user2039789

+0

Хорошо, просто чтобы убедиться, вы знаете, что псевдокод не используется буквально правильно? Просто чтобы это было в первую очередь:] –

+0

Там ya go. Пойдите, получите em. –

Смежные вопросы