Статьи

Учебное пособие по HTML5 Web Audio API: создание виртуальной Synth Pad

Рабочий проект Консорциума World Wide Web Web Audio представляет собой API высокого уровня, который позволяет разработчикам обрабатывать, синтезировать и анализировать аудиосигналы в веб-приложениях, таких как игры HTML5 или виртуальные музыкальные инструменты.

Web Audio использует интерфейс AudioContext для представления AudioNodes. В AudioContext аудиофайл, например, подключен к узлу обработки, который, в свою очередь, связан с пунктом назначения, таким как динамики на вашем ноутбуке. Каждый узел в AudioContext является модульным, так что веб-разработчик может подключить (или отключить) узлы, такие как блоки Lego, блокирующие малыша, для построения относительно более сложных структур.

Один из лучших способов познакомиться с API Web Audio — просто использовать его. В этой статье я собираюсь описать, как создать очень простой виртуальный синтезатор, который будет воспроизводить аудиосэмплы и обеспечивать базовую функцию реверберации. Этот HTML-синтезатор будет далек от инструментов генерации тона, которые используют профессиональные музыканты, но он покажет нам, как:

  • Создать AudioContext
  • Загрузить аудио файлы
  • Воспроизведение аудио файлов
  • Добавить регулятор громкости
  • Петли аудио образцы
  • Остановить воспроизведение аудио
  • Создать эффект реверберации
  • Создать аудио фильтр

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

Создание Synth Pad в нашем HTML

Этот очень простой виртуальный синтезатор будет представлен в веб-браузере, поэтому давайте начнем с разметки, добавив четыре «пэда» на страницу.

Я включил библиотеку jQuery JavaScript через сеть доставки контента Google. jQuery ни в коем случае не требуется для API Web Audio, но его мощные селекторы значительно облегчат взаимодействие с площадками HTML. Я также ссылаюсь на локальный файл JavaScript, который будет содержать код для работы с Web Audio API.

Я назначил атрибут данных каждому из пэдов с информацией о звуковом файле, связанном с каждым пэдом. Вот соответствующий HTML:

<section id="sp"> <div id="pad1" data-sound="kick.wav"></div> <div id="pad2" data-sound="snare.wav"></div> <div id="pad3" data-sound="tin.wav"></div> <div id="pad4" data-sound="hat.wav"></div> </section> 

Я использую CSS, чтобы расположить четыре пэда в сетке два на два, так как это будет стандартная конфигурация для небольшого синтезаторного пэда. Я установил значение ширины для элемента <section> и теперь каждый элемент ‘pad’ отображается в виде встроенного блока.

Создание AudioContext

Давайте начнем сценарий. Я создаю новый AudioContext с одной строкой.

 var context = new AudioContext(); 

Загрузка аудио файлов

Следующая задача — написать функцию, которая будет загружать аудиофайлы. Эта функция будет:

  • Примите URL для аудио файла
  • Загрузите этот файл через XMLHttpRequest
  • Декодируйте аудио для использования в AudioContext
  • Предоставить некоторые средства доступа к декодированному источнику.

Вот:

 function loadAudio( object, url) { var request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'arraybuffer'; request.onload = function() { context.decodeAudioData(request.response, function(buffer) { object.buffer = buffer; }); } request.send(); } 

Функция loadAudio которую я написал для нашей виртуальной панели синтезатора, принимает два параметра. Первый параметр — это объект pad. Второй параметр — это URL для звукового файла, который будет загружать функция.

Переменной request назначается новый объект XMLHttpRequest. Мы передаем три параметра методу open() запроса, указав метод связи (в данном случае GET), URL-адрес аудиофайла и значение «true», чтобы указать, что мы хотим асинхронный запрос.

Тип ответа на запрос установлен в «arraybuffer» для обработки двоичного аудиофайла.

 var request = new XMLHttpRequest(); request.open('GET', url, true); request.responseType = 'arraybuffer'; 

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

Метод decodeAudioData() имеет два обязательных параметра. Первым из них является аудиофайл, который он должен декодировать. В нашем скрипте этот файл хранится как «request.response». Вторым обязательным параметром является функция обратного вызова. Для функции обратного вызова я использовал вторую анонимную функцию для добавления свойства к объекту pad. Это новое свойство будет простым способом доступа к узлу аудиоисточника.

 request.onload = function() { context.decodeAudioData(request.response, function(buffer) { object.buffer = buffer; }); } 

Метод send() запроса, конечно же, также добавляется в скрипт.

Воспроизведение аудиофайла при нажатии на пэд

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

Было несколько способов управления отношениями со звуковой панелью, но в конце концов я решил расширить, если хотите, объект элемента <div> , добавив связанные со звуком свойства в саму панель <div> в качестве средства создание вышеупомянутой ассоциации.

Таким образом, addAudioProperties() принимает параметр объекта элемента pad и добавляет к этому объекту три свойства. Четвертое свойство добавляется, когда пэд «проигрывается».

 function addAudioProperties(object) { object.name = object.id; object.source = $(object).data('sound'); loadAudio(object, object.source); object.play = function () { var s = context.createBufferSource(); s.buffer = object.buffer; s.connect(context.destination); s.start(0); object.s = s; } } 

Первая строка в функции устанавливает значение для свойства «name», чтобы оно соответствовало атрибуту id элемента pad, а именно «pad1», «pad2», «pad3» и «pad4».

 object.name = object.id; 

Следующие две строки в функции устанавливают свойство «source» в соответствии со значением атрибута data-sound HTML, который я включил в каждый из элементов <div> loadAudio , и эффективно loadAudio как объект, так и источник в функцию loadAudio загрузка звукового файла в буфер. Вы можете думать о буфере как о месте в системной памяти, в котором хранятся ваши звуки, пока вы не будете готовы их воспроизвести.

 object.source = $(object).data('sound'); loadAudio(object, object.source); 

Затем функция предоставляет объекту pad метод play . Этот метод имеет пять задач.

  • Он вызывает метод createBufferSource AudioContext, создавая новый узел источника createBufferSource
  • Он устанавливает свойство источника узла
  • Он подключает источник звука к динамикам вашего компьютера
  • Играет звук
  • Он присоединяет источник звука к свойству объекта pad

Вот функция:

 object.play = function () { var s = context.createBufferSource(); s.buffer = object.buffer; s.connect(context.destination); s.start(0); object.s = s; } 

Давайте рассмотрим пару из этих задач более подробно.

Сначала метод createBufferSource() помещает новый узел в AudioContext.

Во-вторых, новый узел связан с context.destination . Этот пункт назначения является специальным узлом, представляющим вывод звука по умолчанию вашей системы. Обычно это будут динамики вашего компьютера по умолчанию или, возможно, наушники, подключенные к вашему компьютеру.

Также обратите внимание, что я использовал селектор jQuery и метод jQuery data() чтобы немного облегчить доступ к атрибуту data-sound .

Теперь нам нужно привести в действие наши новые функции и AudioContext.

Я использовал jQuery для создания хорошо известной анонимной функции готовности документа, которая автоматически вызывается при загрузке страницы:

 $(function() { }); 

Когда страница загружается, я хочу пойти дальше и расширить объекты элемента pad. Этот код использует jQuery для выбора каждого элемента pad и итерации по каждому addAudioProperties() , вызывая addAudioProperties() для каждого.

 $('#sp div').each(function() { addAudioProperties(this); }); 

Функция готовности документа также начинает прослушивать, если хотите, события щелчка на элементах панели. Когда происходит событие click, виртуальный синтезатор вызывает метод play() объекта pad.

 $('#sp div').click(function() { this.play(); }); 

Вот функция готового документа со всеми его частями и частями до сих пор.

 $(function() { $('#sp div').each(function() { addAudioProperties(this); }); $('#sp div').click(function() { this.play(); }); }); 

После сохранения всех ваших файлов и загрузки виртуальной панели синтезатора в Chrome, Firefox, Safari или Opera у вас должна быть функциональная панель синтезатора. Когда вы нажимаете на пэд, звучит звук.

Добавить регулятор громкости

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

Для этого элемента управления потребуется немного дополнительного HTML и CSS, чтобы добавить раздел панели управления и четыре элемента div элемента управления ниже существующей разметки для пэдов. HTML для каждого элемента панели управления выглядит следующим образом:

 <div data-pad="pad1"> <h2>TL Control</h2> <h3>top left pad</h3> <label for"volume 1">Volume</label> <input type="range" min="0" max="5" step="0.1" value="1" data-control="gain" name="volume1"> </div> 

Обратите внимание, что я использовал элемент ввода диапазона для регулировки громкости. Каждый из входных элементов имеет атрибут data-control со значением «усиление». В API Web Audio интерфейс узла усиления фактически представляет изменение громкости звука.

Нам нужно добавить регулятор усиления или громкости к объекту pad. Это дополнение потребует:

  • Новый узел усиления
  • Обновление метода play() для маршрутизации источника звука через узел усиления.

AudioContext имеет простой метод для создания узла усиления.

 object.volume = context.createGain(); 

В методе play() я просто подключил источник к узлу усиления, а затем подключил узел усиления к месту назначения.

 s.connect(object.volume); object.volume.connect(context.destination); 

Обновленная addAudioProperties() всего на две строки длиннее, что указано в комментариях в приведенном ниже коде:

 function addAudioProperties(object) { object.name = object.id; object.source = $(object).data('sound'); loadAudio(object, object.source); object.volume = context.createGain(); // new line object.play = function () { var s = context.createBufferSource(); s.buffer = object.buffer; s.connect(object.volume); object.volume.connect(context.destination); // new line s.start(0); object.s = s; } } 

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

 $('#cp input').change(function() { var v = $(this).parent().data('pad'), pad = $('#' + v)[0]; switch ($(this).data('control')) { case 'gain': pad.volume.gain.value = $(this).val(); break; default: break; } }); 

Этот фрагмент кода имеет четыре дела.

  • Контролирует входы панели управления
  • Определяет, какой пэд связан с регулятором громкости
  • Он использует оператор switch для определения цели ввода
  • Это меняет громкость звука

В jQuery есть метод change() который будет запускаться при любом изменении одного из элементов ввода диапазона громкости. Метод change() принимает функцию обратного вызова в качестве параметра, позволяя сценарию выполнять некоторые действия — например, изменять уровень громкости.

В HTML для элементов управления я поместил атрибут данных, чтобы определить, какая виртуальная панель синтезатора связана с данным элементом управления. Значение пэда («pad1», «pad2», «pad3» или «pad4») сохраняется в переменной v , которая определяет правильный синтезаторный пэд.

 $('#cp input').change(function()... 

Второй переменной, pad , назначается объект элемента pad. jQuery допускает этот вид сцепленного селектора, где «#» объединяется со значением пэда, например «pad1», которое выбирается как «# pad1».

 pad = $('#' + v)[0]; 

Оператор switch JavaScript учитывает атрибут data-control ввода диапазона. Когда значением атрибута data-control является «усиление», код обновляет свойство объекта volume.gain.value элемента volume.gain.value , изменяя громкость звука.

 switch ($(this).data('control')) { case 'gain': pad.volume.gain.value = $(this).val(); break; default: break; } 

На этом этапе виртуальный синтезатор имеет функциональные регуляторы громкости.

Добавление функции Audio Loop

Виртуальному синтезатору требуется возможность многократного воспроизведения одного сэмпла. Итак, мы собираемся добавить кнопку «Loop» на панель управления. Эта функция цикла будет воспроизводить связанный аудиосэмпл снова, как только он закончится.

Нам нужно добавить немного больше HTML для отображения кнопки «Цикл».

 <button type="button" class="loop-button" data-toggle-text="End Loop" value="false">Loop</button> 

Запишите класс кнопки, ее значение и атрибут данных, так как все они будут указаны в нашем JavaScript.

Чтобы упростить функцию цикла, я сделал три изменения в функции addAudioProperties() , добавив новое свойство loop в объект; установка свойства loop источника в значение свойства loop объекта pad внутри метода play() ; и добавив метод stop() . Помните, что остановка источника звука была также одной из наших целей, упомянутых в начале статьи, и это действительно так просто.

 function addAudioProperties(object) { object.name = object.id; object.source = $(object).data('sound'); loadAudio(object, object.source); object.volume = context.createGain(); object.loop = false; object.play = function () { var s = context.createBufferSource(); s.buffer = object.buffer; s.connect(object.volume); object.volume.connect(context.destination); s.loop = object.loop; s.start(0); object.s = s; } object.stop = function () { if(object.s) object.s.stop(); } } 

Внутри функции готовности документа я добавил код для прослушивания нажатий кнопок. Этот код имеет семь задач.

  • Определите связанный пэд
  • Установите переменную в текстовое значение кнопки, в данном случае «Loop»
  • Установите переменную, равную объекту pad div
  • Используйте оператор switch для определения цели кнопки
  • Остановить воспроизведение аудиоисточника
  • Поменяйте местами текст кнопки со значением атрибута данных
  • Установите значение цикла объекта pad pad

Вот код:

 $('#cp button').click(function() { var v = $(this).parent().data('pad'), toggle = $(this).text(), pad = $('#' + v)[0]; switch ($(this)[0].className) { case 'loop-button': pad.stop(); $(this).text($(this).data('toggleText')).data('toggleText', toggle); ($(this).val() === 'false') ? $(this).val('true') : $(this).val('false'); pad.loop = ($(this).val() == 'false') ? false : true; break; default: break; } }); 

Давайте рассмотрим каждый из этих шагов более подробно.

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

 var v = $(this).parent().data('pad'), 

Следующим двум переменным присваивается значение текста кнопки, которое в данном случае является «Loop» и объектом элемента pad соответственно. JQuery делает эти выборы очень легко.

 toggle = $(this).text(), pad = $('#' + v)[0]; 

Оператор switch просматривает имя класса кнопки. Я использовал имя класса как способ определения цели кнопки, если хотите. Здесь снова утверждение switch несколько излишне, но я знаю, что мы собираемся добавить еще две кнопки на виртуальную панель синтезатора, поэтому использование этого теперь избавляет нас от некоторых проблем позже.

 switch ($(this)[0].className) { case 'loop-button': pad.stop(); $(this).text($(this).data('toggleText')).data('toggleText', toggle); ($(this).val() === 'false') ? $(this).val('true') : $(this).val('false'); pad.loop = ($(this).val() == 'false') ? false : true; break; default: break; } 

Первая строка в выражении switch для случая «loop-button» вызывает метод stop() объекта pad, который я только что добавил.

Если вы не очень хорошо знакомы с jQuery, следующая строка кода может выглядеть сложной.

 $(this).text($(this).data('toggleText')).data('toggleText', toggle); 

Первый раздел представляет собой простой селектор jQuery, фиксирующий элемент кнопки (то есть «это»).

Метод text() здесь устанавливает значение текста кнопки равным значению атрибута «data-toggle-text» кнопки. В частности, это заставит кнопку читать «End Loop», а не «Loop».

Двигаясь дальше вниз по цепочке, метод data() используется для установки значения атрибута data-toggle-text равным значению переменной toggle, который только несколько минут назад я установил в значение текста кнопки, прежде чем мы изменили этот текст. По сути, у меня был текст кнопки, который изначально был «Loop», поменялся местами со значением атрибута data-toggle-text , который изначально был «End Loop». Каждый раз при нажатии кнопки «Loop» и «End» Петля »поменяется местами.

Следующие две строки кода работают вместе, чтобы обновить свойство loop объекта pad pad.

 ($(this).val() === 'false') ? $(this).val('true') : $(this).val('false'); pad.loop = ($(this).val() == 'false') ? false : true; 

Условный троичный оператор проверяет значение кнопки. Если значение в настоящий момент равно false, это значение изменяется на true. Аналогично, если бы текущее значение было истинным, оно было бы изменено на ложное — поскольку значение кнопки до щелчка представляет противоположность намерениям пользователя.

Может показаться, что теперь я могу установить значение свойства loop объекта pad pad равным значению кнопки, но это не совсем работает. Значение кнопки является строкой, но свойство цикла требует логического значения. Таким образом, я использовал второй троичный оператор для передачи правильного логического значения. Я полагаю, я мог бы также изменить тип.

Виртуальная панель синтезатора теперь имеет функцию петли.

Создать эффект реверберации

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

Для виртуальной панели синтезатора я использую файл импульсного отклика, представляющий довольно большой зал. Этот файл импульсного ответа был получен от проекта Chris Audio Wilson’s Web Audio API Playground на Github и может свободно использоваться по лицензии MIT. Кстати, Крис Уилсон — адвокат разработчика в Google и редактор рабочего проекта Web Audio API .

Как и прежде, мне понадобится дополнительный HTML-код для размещения кнопки реверберации на странице виртуальной панели синтезатора. HTML здесь почти идентичен HTML для кнопки цикла.

 <button type="button" class="reverb-button" data-toggle-text="No Rvrb" value=false>Reverb</button> 

Следующим шагом в процессе добавления этого узла является добавление новой функции, которая будет загружать аудиофайл с импульсной характеристикой. Эта функция создаст объект реверберации и затем использует функцию laodAudio для добавления звука импульсного отклика в буфер. Здесь нет новых концепций.

 function reverbObject (url) { this.source = url; loadAudio(this, url); } 

В функции addAudioProperties() мне нужно добавить одну строку кода, создающую свойство для представления реверберации.

 object.reverb = false; 

Метод play() объекта элемента div div также необходимо обновить. В данный момент источник звука подключен к узлу усиления, а узел усиления подключен к динамикам. Когда пользователь нажимает кнопку реверберации, нам нужно вставить в эту цепочку узел свертки, чтобы источник звука подключался к узлу усиления, узел усиления соединялся с узлом усиления, а узел свертки подключался к динамикам.

Посмотрите на метод play() как и до этих изменений.

 object.play = function () { var s = context.createBufferSource(); s.buffer = object.buffer; s.connect(object.volume); object.volume.connect(context.destination); s.loop = object.loop; s.start(0); object.s = s; } 

Я взял строку кода, соединяющую узел усиления «object.volume» с динамиками, и заменил ее конструкцией if-else.

 object.play = function () { var s = context.createBufferSource(); s.buffer = object.buffer; s.connect(object.volume); if (this.reverb === true) { this.convolver = context.createConvolver(); this.convolver.buffer = irHall.buffer; this.volume.connect(this.convolver); this.convolver.connect(context.destination); } else if (this.convolver) { this.volume.disconnect(0); this.convolver.disconnect(0); this.volume.connect(context.destination); } else { this.volume.connect(context.destination); } s.loop = object.loop; s.start(0); object.s = s; } 

Первая часть оператора if проверяет, установлено ли для свойства элемента реверберации элемента pad значение true. Если свойство имеет значение true, создается узел свертки, файл импульсного отклика идентифицируется и узлы подключаются.

Если свойство reverb имеет значение false, метод проверяет, есть ли уже связанный с источником узел свертки. Если есть узел конволера и, как мы уже знаем, свойство реверберации имеет значение false, то пользователь должен был нажать кнопку реверберации, чтобы отключить его. Таким образом, сценарий отключает узел усиления и узлы свертки и повторно подключает узел усиления непосредственно к динамикам.

Если свойство реверберации имеет значение false и не существует существующего узла свертки, узел усиления будет подключен непосредственно к динамикам.

Функция реверберации также должна быть подключена к функции готовности документа jQuery.

Вот посмотрите на часть функции готовности документа, которая слушает кнопку цикла, поскольку у нас есть кодированная виртуальная панель синтезатора прямо сейчас.

 $('#cp button').click(function() { var v = $(this).parent().data('pad'), toggle = $(this).text(), pad = $('#' + v)[0]; $(this).text($(this).data('toggleText')).data('toggleText', toggle); ($(this).val() === 'false') ? $(this).val('true') : $(this).val('false'); switch ($(this)[0].className) { case 'loop-button': pad.stop(); pad.loop = ($(this).val() == 'false') ? false : true; break; default: break; } }); 

Добавление нового регистра в операторе switch — это все, что требуется. Этот новый случай очень похож на код, созданный для кнопки цикла:

 case 'reverb-button': pad.stop(); pad.reverb = ($(this).val() == 'false') ? false : true; break; 

В качестве последнего шага в функцию готовности документа вставляется новая строка кода для добавления файла импульсного отклика в буфер.

 irHall = new reverbObject('irHall.ogg'); 

Функция реверберации виртуального синтезатора теперь работает.

Создание аудио фильтра

Виртуальный синтезатор начинает становиться забавным, но я хочу добавить еще одну особенность: аудиофильтр. У Web Audio API есть несколько способов манипулировать звуками, но мы собираемся сосредоточиться на простом примере с причудливым именем, а именно узле низкочастотного фильтра биквад.

В HTML я добавил новую кнопку «Фильтр» и два диапазона ввода для частоты и качества.

 <button type="button" class="filter-button" data-toggle-text="No Fltr" value=false>Filter</button> <lable class="filter-group faded" for="frequency1">Frequency:</lable> <input class="filter-group faded" type="range" min="0" max="10000" step="1" value="350" data-control="fq" name="frequency1"> <lable class="filter-group faded" for="quality1">Quality:</lable> <input class="filter-group faded" type="range" min="0.0001" max="1000" step="0.0001" value="500" data-control="q" name="quality1"> 

Запомните диапазоны частотных и качественных входов. Коэффициент качества, например, задается для номинального диапазона узлов фильтра биквада. Также не «исчезнувший» класс. Когда секция управления загружается, я хочу, чтобы входы аудио-фильтра выглядели блеклыми, указывая на то, что они недоступны. Когда пользователь нажимает кнопку фильтра, входные значения диапазона оживают, если хотите.

Объекту pad pad нужны три новых свойства, чтобы установить логическое значение, установить значение частоты по умолчанию и установить значение качества по умолчанию. Эти свойства, конечно, добавляются в addAudioProperties() .

 object.filter = false; object.fqValue = 350; object.qValue = 500; 

Метод play() объекта pad также нуждается в нескольких условных выражениях. Концепция здесь очень похожа на оператор if который мы добавили с помощью функции реверберации. Код должен правильно соединять узлы в зависимости от того, задействованы ли циклы, реверберация и фильтрация.

 if (this.filter === true) { this.biquad = context.createBiquadFilter(); this.biquad.type = this.biquad.LOWPASS; this.biquad.frequency.value = this.fqValue; this.biquad.Q.value = this.qValue; if (this.reverb === true) { this.convolver.disconnect(0); this.convolver.connect(this.biquad); this.biquad.connect(context.destination); } else { this.volume.disconnect(0); this.volume.connect(this.biquad); this.biquad.connect(context.destination); } } else { if (this.biquad) { if (this.reverb === true) { this.biquad.disconnect(0); this.convolver.disconnect(0); this.convolver.connect(context.destination); } else { this.biquad.disconnect(0); this.volume.disconnect(0); this.volume.connect(context.destination); } } } 

Далее нам нужно внести изменения в функцию готовности документа. Первое из этих изменений — добавить поддержку кнопки фильтра. Это будет новый случай в операторе switch . Обратите внимание, что я добавил немного jQuery, чтобы переключать «исчезающий» класс, который мы добавили к меткам и входам фильтра.

 case 'filter-button': pad.stop(); pad.filter = ($(this).val() == 'false') ? false : true; $(this).parent().children('.filter-group').toggleClass('faded'); break; 

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

 case 'fq': pad.fqValue = $(this).val(); break; case 'q': pad.qValue = $(this).val(); break; 

Функция фильтра теперь работает.

Заключение и Демо

В этом учебном пособии мы попытались дать базовое представление о мощном API Web Audio. Если вы следовали ему, у вас должна быть виртуальная (и шумная) панель синтезатора, а также лучшее понимание основных функций Web Audio.

Чтобы увидеть синтезатор в действии, посетите эту демонстрационную страницу . Вы также можете скачать исходные файлы или возиться с кодом на CodePen . Стоит отметить одну вещь: CodePen, кажется, вызывает ошибку, которая препятствует загрузке одного из файлов в Chrome. Этого не происходит в HTML-демонстрации, и он должен нормально работать в Firefox в обеих демонстрациях.

Web Audio API поддерживается во всех современных настольных браузерах, но не в IE11.