2012-03-01 11 views
20

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

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

(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

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

+0

Возможно, это отправная точка: http://www.storiesinflight.com/jsfft/visualizer/index.html – Mika

+0

@ Мика, он звонит в далекий демо-звонок. – katspaugh

+0

Это по теме: http://softwarerecs.stackexchange.com/ – kenorb

ответ

9

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

+0

Вадим, это почти то, что я хотел. Они не генерируют графику сигналов (она загружается из SoundCloud), но ее легко добавить с помощью ['RealtimeAnalyserNode'] (https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification. HTML # д.ф.н.-getByteTimeDomainData). Большое спасибо! – katspaugh

39

В свою очередь, у меня была своя библиотека: wavesurfer.js.

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

Imgur

+0

Как я могу построить форму сигналов локальных аудиофайлов (которые не размещены на сервере, но доступны в другом каталоге моего ПК). Возможно ли это с вашим js? – madLokesh

+0

@madLokesh, да, можно создавать файлы с помощью File API (http://dev.w3.org/2006/webapi/FileAPI/). – katspaugh

+0

Я использую Кордову, поэтому я должен использовать File API для Кордовы для доступа к файлу, но как передать аудиофайл. В качестве закодированного base64 URl или в качестве буфера массива – madLokesh

2

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

Это все с открытым исходным кодом и предназначено для модульности (и незавершенного)

Вы можете найти demo over here
И соответствующего githug repository

+0

Ницца, спасибо ! – katspaugh

+0

Upvote for cuddly git = D – CoDEmanX

+1

Обе ссылки 404. –

0

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

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

Вот пример алгоритма, который делает это, но позволяет вам давать образцы на пиксель в качестве аргумента, а также позицию прокрутки, чтобы разрешить виртуальную прокрутку и масштабирование. Она включает в себя параметр разрешения можно настроить для работы, это указывает на то, сколько образцов она должна принимать в пределах выборки пикселей: Drawing zoomable audio waveform timeline in Javascript

Метод Жеребьевка есть схожие с вашими, чтобы сгладить его, вы должны использовать LineTo вместо of 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 
} 

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

  • Нет связанных вопросов^_^