• Главная»
  • Уроки»
  • HTML5»
  • Руководство по HTML5 Web Audio API: делаем виртуальный синтезатор

Руководство по HTML5 Web Audio API: делаем виртуальный синтезатор

demosourse

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

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

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

  • создавать АудиоКОнтекст;
  • загружать аудио файлы;
  • проигрывать аудио файлы;
  • добавить управление громкостью;
  • зациклить аудио фрагмент;
  • остановить проигрывание звука;
  • реализовать эффект реверберации;
  • реализовать аудио фильтр.

Делаем синтезатор в HTML

Этот простейший синтезатор будет выводиться в браузере, так что начнём мы с разметки, и добавим на страницу четыре “клавиши”.

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

Каждой кнопке я присвоил data-атрибут с информацией о том аудио файле, с которым ассоциирована эта клавиша. Вот соответствующий 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 я разместил эти элементы сеткой 2x2, что является стандартной конфигурацией для малых синтезаторов. Элементу <section> задал ширину, а каждая клавиша отображается как строчно-блочный элемент.

Создаём АудиоКонтекст

Давайте приступим к написанию кода. Я создаю новый АудиоКОнтекст с помощью простой строчки кода:

var context = new AudioContext();

Загружаем аудио файлы

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

  • принимать URL аудио файла;
  • загружать файл посредством XMLHttpRequest;
  • декодировать аудио для использования с АудиоКонтекстом;
  • обеспечивать средства доступа к загруженному файлу.

А вот и код функции:

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, которую я написал для нашего виртуального синтезатора, принимает два параметра. Первый параметр - объект клавиши. Второй параметр - URL звукового файла, который будет загружен с помощью функции.

Переменной request приравнивается новый объект XMLHttpRequest. В метод open() нашего запроса мы передаём три параметра, указывая тип запроса (в нашем случае GET), URL аудио файла, и true, который указывает, что мы хотим, чтобы файл был загружен асинхронно.

Тип ответа устанавливается в “arraybuffer”, чтобы указать, что мы обрабатываем двоичный аудио файл.

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

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

У метода decodeAudioData() есть два обязательных параметра. Первый - это аудио файл, который надо декодировать. В нашем скрипте этот файл хранится в “request.response”. Второй обязательный параметр - функция обратного вызова. В качестве функции обратного вызова я использовал ещё одну анонимную функцию, которая добавляет свойство к объекту клавиши. С помощью этого свойства мы легко можем получить доступ к исходному аудио узлу.

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

Разумеется, в скрипте также вызывается метод send() объекта запроса.

Проигрывание аудио файла при клике на клавишу

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

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

Итак, функция addAudioProperties() принимает объект элемента кнопки, и добавляет к нему три свойства. Четвёртое свойство добавляется в момент, когда кнопка “проигрывается”.

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 кнопки, соответственно “pad1”, “pad2”, “pad3” и “pad4”.

object.name = object.id;

Следующие две строки функции устанавливают значение свойства “source” в значение data-атрибута data-sound, который я определил для каждой кнопки, и передаёт как объект, так и ссылку на источник в функцию loadAudio, загружая файл в буфер. Можно сказать, он играет роль места в памяти, в котором хранится звук в ожидании момента, когда его захотят проиграть.

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

Далее функция определяет объекту кнопки метод play. Этот метод совершает пять действий:

  • вызывает метод createBufferSource АудиоКонтекста, создавая новый узел со звуком в сцене;
  • устанавливает свойство источника для узла;
  • подключает источник звука к динамикам компьютера;
  • проигрывает звук;
  • присваивает источник звука свойству s объекта кнопки.

Вот и функция:

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

Давайте рассмотрим некоторый из этих действий более тщательно.

Первым делом, метод createBufferSource() размещает новый узел в АудиоКонтексте.

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

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

Теперь надо заставить работать наши новые функции и АудиоКонтекст.

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

$(function() {

});

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

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

В функции document.ready также можно задать обработчики события onclick для каждой кнопки. Когда по кнопке кликают - синтезатор вызывает метод play() у объекта кнопки.

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

Вот наша функция document.ready со всеми вышеописанными фрагментами кода.

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

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

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

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

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

Такой элемент управления потребует дополнительной HTML разметки и CSS - необходимо добавить дополнительные блоки с элементами управления для каждой из клавиш синтезатора. 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>

Заметьте - я использовал элемент управления “range” для управления громкостью. Каждый элемент управления имеет атрибут data-control со значением усиления проигрываемого звука. В Web Audio API узел усиления представляет собой изменение в громкости звука.

Нам необходимо добавить управление усилением или громкостью к объекту клавиши Это потребует:

  • новый узел усиления;
  • дополнить метод play(), чтобы направить источник звука через узел усиления.

У АудиоКонтекста есть простой метод для создания узла усиления.

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(); // новая строка
    object.play = function () {
        var s = context.createBufferSource();
        s.buffer = object.buffer;
        s.connect(object.volume);
        object.volume.connect(context.destination); // новая строка
        s.start(0);
        object.s = s;
    }
}

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

$('#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 регуляторам я назначил data-атрибут, который определяет, какая клавиша синтезатора ассоциирована с данным регулятором. Значение (“pad1,” “pad2,” “pad3,” или “pad4”) хранится в переменной v, которая указывает на соответствующую клавишу синтезатора.

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

Вторая переменная (pad) присвоена объекту клавиши синтезатора. jQuery позволяет использовать конкатенированный селектор, где знак “#” объединяется с именем клавиши, например, “pad1”, то есть выбирать мы будем “#pad1”.

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

Оператор switch сравнивает значение data-атрибута data-control регулятора. В случае, когда значение атрибута равно “gain”, код обновляет свойство volume.gain.value объекта клавиши, что меняет громкость звука.

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

На этом этапе у нашего синтезатора есть возможность контролировать громкость звуков посредством регуляторов.

Добавляем возможность зацикливания проигрывания

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

Добавим ещё немного HTML для отображения кнопки повтора.

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

Обратите внимание на класс, значение и data-атрибут кнопки, так как ко всем этим параметрам мы будем обращаться в нашем JavaScript.

Для реализации функции зацикливания я сделал три изменения в функции addAudioProperties():

  • добавил новое свойство loop к объекту;
  • установил свойство loop внутри метода play(), stop();
  • добавил метод 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();
    }
}

Внутри функции document.ready я добавил немного кода, который будет отслеживать клики по кнопкам. Этот код делает семь действий:

  • определяет связанную клавишу;
  • устанавливает переменной значение текста кнопки, в нашем случае - “Loop”;
  • приравнивает переменную к объекту клавиши синтезатора;
  • использует оператор switch для определения того, что должна сделать кнопка;
  • останавливает проигрывание звука;
  • меняет местами текст кнопки и значение data-атрибута;
  • устанавливает флаг повтора объекту клавиши.

А вот и код:

$('#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”, и, соответственно, объекта клавиши. Их легко найти с помощью 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;
}

Первая строчка в секции “loop-button” вызывает у объекта кнопки свежедобавленный метод stop().

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

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

Первый фрагмент - просто jQuery селектор, который выбирает элемент кнопки (то есть, “this”).

Метод text() устанавливает значение текста кнопки в значение из data-атрибута “data-toggle-text”. Проще говоря, теперь вместо “Loop” кнопка будет называться “End Loop”.

Идя дальше по цепочке можно видеть, что метод data() используется для того, чтобы установить значение атрибута data-toggle-text в то значение, которое было у текста кнопки до того, как мы изменили ее текст. В общем, сначала у нас была кнопка с текстом “Loop”, а data-атрибут имел значение “End Loop”, а в результате работы этой строчки эти значения поменялись местами. При каждом клике по кнопке текст кнопки и значение data-атрибута будут меняться местами (“Loop” и “End loop”).

Следующие две строки кода используются для обновления флага зацикливания у объекта клавиши.

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

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

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

Теперь наш синтезатор расширен функцией зацикливания звуков.

Реализуем эффект реверберации

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

Для нашего синтезатора я использую файл импульсной характеристики, который представляет большое помещение. Эта импульсная характеристика была позаимствована с проекта Web Audio API Playground Криса Вилсона на Github, и её можно свободно использовать по условию лицензии MIT.

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

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

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

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

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

object.reverb = false;

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

Давайте посмотрим на метод 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 проверяет, если свойство reverb у объекта клавиши синтезатора установлено в true. Если это так - то необходимо создать узел коррелятора, загрузить файл с импульсной характеристикой, и подключить эти узлы.

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

Если свойство reverb=fale, но узел коррелятора ещё не создавался, узел усиления будет подключён напрямую к колонкам.

Обработку кнопки реверберации также надо прописать в jQuery функции document.ready.

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

$('#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;

Последним шагом добавим новую строчку кода в функцию document.ready, которая загрузит файл импульсной характеристики в буфер.

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">

Обратите внимание на диапазоны частоты и качества. Диапазон показателя качества, например, равен номинальному диапазону узла биквадратного фильтра. Также обратите внимание на класс “faded”. При загрузке панели управления я хочу, чтобы элементы управления выглядели как недоступные для изменения. Когда пользователь кликает по кнопке фильтра, регуляторы активируются.

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

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

Метод play() объекта клавиши также требует несколько дополнительных условий. Этот подход очень похож на условие 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);
        }
    }
}

Далее необходимо внести изменения в функцию document.ready. Первым делом добавим поддержку кнопки фильтра. Это будет новое условие в секции switch. Заметьте, что я написал немного jQuery-кода для переключения класса "faded", который мы добавили к меткам и полям ввода.

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

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

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

Теперь у нас ещё и фильтры есть!

Заключение

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

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: http://www.sitepoint.com/html5-web-audio-api-tutorial-building-virtual-synth-pad/
Перевел: Станислав Протасевич
Урок создан: 17 Октября 2014
Просмотров: 18918
Правила перепечатки


5 последних уроков рубрики "HTML5"

  • Расширяем возможности HTML за счёт создания собственных тегов

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

  • Определение доступности атрибута HTML5 с помощью JavaScript

    Сегодня мы посмотрим, как можно организовать проверку доступности атрибута HTML5 с помощью JavaScript. Проверять будем работу элементов details и summary.

  • HTML5: API работы с вибрацией

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

  • Создание форм с помощью Webix Framework — 4 практических примера

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

  • Знакомство с фрэймворком Webix

    В этой статье мы бы хотели познакомить вас с фрэймворком Webix. Для демонстрации возможностей данного инструмента мы создадим интерфейс online аудио плеера. Не обольщайтесь — это всего лишь модель интерфейса. Исходный код доступен в демо и на странице GitHub.

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 20 Октября 2014 10:07
    TF03
    У меня не работает демка, при загрузке страницы в консоли пишет: Uncaught ReferenceError: AudioContext is not defined. если что браузер - Google Chrome
    • 20 Октября 2014 16:13
      stas.protasevich
      какая у вас версия Google Chrome?
    • 3 Августа 2015 19:33
      Tankizzzt
      У меня демо работает если перейти по ссылке вверху, а если скачать на компьютер и запустить то звук не идет. Хром мозила опера последние
      • 17 Августа 2015 12:44
        stas.protasevich
        Следует запускать с локального сервера
  • 7 Октября 2015 01:05
    Kudesnic
    Спасибо за интересный урок, пригодился при написании модуля драм-машины в дипломной работе. Вот результат http://online-audio-redaktor.esy.es/#
^ Наверх ^