Web Audio для визуализации и взаимодействия с сигналами - PullRequest
22 голосов
/ 01 марта 2012

Как мне написать программу JavaScript для отображения формы сигнала из аудиофайла? Я хочу использовать Web Audio и Canvas.

Я попробовал этот код:

(new window.AudioContext).decodeAudioData(audioFile, function (data) {
   var channel = data.getChannelData(0);
   for (var i = 0; i < channel; i++) {
       canvas.getContext('2d').fillRect(i, 1, 40 - channel[i], 40);
   }
});

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

Waveform example

Любые советы о том, как реализовать форму волны?

Ответы [ 4 ]

42 голосов
/ 15 марта 2012

В конце концов выкатил свою собственную библиотеку: wavesurfer.js .

Он рисует форму волны из данных PCM и ищет области аудио, нажимая на нее.

Imgur

9 голосов
/ 06 марта 2012

Вас может заинтересовать AudioJedit . Это проект с открытым исходным кодом , размещенный на GitHub . Он имеет небольшой серверный скрипт node.js для загрузки аудиофайлов, но все взаимодействие со звуком реализовано в клиентском JavaScript. Я думаю, что это похоже на то, что вы ищете.

2 голосов
/ 23 июня 2014

Для простого ( * ) простого использования и интеграции осциллограммы с вашим приложением вы можете проверить, что мы делаем в IRCAM, особенно осциллограммы в данном конкретном случае.

Это все с открытым исходным кодом и нацелено на модульность (и работа в процессе)

Здесь вы можете найти демо
И соответствующий репозиторий githug

0 голосов
/ 17 ноября 2017

Ваш код рендеринга крайне неэффективен, потому что он рендерит 44100 пикселей за каждую секунду звука. Желательно визуализировать не более ширины области просмотра с уменьшенным набором данных.

Диапазон выборки на пиксель, необходимый для соответствия сигнала в области просмотра, можно рассчитать с помощью audioDurationSeconds * samplerate / viewPortWidthPx. Таким образом, для области просмотра 1000 пикселей и аудиофайла в 2 секунды с частотой дискретизации 44100 выборок на пиксель = (2 * 44100) / 1000 = ~ 88. Для каждого пикселя на экране вы берете минимальное и максимальное значение из этого диапазона выборки, вы используете эти данные для рисования формы волны.

Вот пример алгоритма, который делает это, но позволяет вам давать выборки на пиксель в качестве аргумента, а также позицию прокрутки, чтобы обеспечить виртуальную прокрутку и масштабирование. Он включает параметр разрешения, который вы можете настроить для повышения производительности, он указывает, сколько сэмплов должно быть взято на пиксельный диапазон сэмплов: Рисование масштабируемой временной шкалы формы звукового сигнала в Javascript

Метод рисования там похож на ваш, чтобы сгладить его, вам нужно использовать lineTo вместо fillRect. На самом деле это различие не должно быть таким огромным, я думаю, вы можете забыть установить атрибуты width и height холст. Установка этого в css вызывает размытое рисование, вам нужно установить атрибуты.

let drawWaveform = function(canvas, drawData, width, height) {
   let ctx = canvas.getContext('2d');
   let drawHeight = height / 2;

   // clear canvas incase there is already something drawn
   ctx.clearRect(0, 0, width, height);

   ctx.beginPath();
   ctx.moveTo(0, drawHeight);
   for(let i = 0; i < width; i++) {
      // transform data points to pixel height and move to centre
      let minPixel = drawData[i][0] * drawHeigth + drawHeight;
      ctx.lineTo(i, minPixel);
   }
   ctx.lineTo(width, drawHeight);
   ctx.moveTo(0, drawHeight);
   for(let i = 0; i < width; i++) {
      // transform data points to pixel height and move to centre
      let maxPixel = drawData[i][1] * drawHeigth + drawHeight;
      ctx.lineTo(i, maxPixel);
   }
   ctx.lineTo(width, drawHeight);
   ctx.closePath();
   ctx.fill(); // can do ctx.stroke() for an outline of the waveform
} 
...