Назад в библиотеку

Начало работы с аудио WEB-API

Автор: Boris Smus

Автор перевода: Лёгенький Б.В.

Введение

Тег audio в HTML5, Flash или иной плагин должен быть отключен. Аудио теги приносят существенные ограничения для реализации сложных игр и интерактивных приложений.Web Audio API, на высоком уровне JavaScript API для обработки и синтеза звука в веб-приложениях. Целью данного API будет включение возможностей, имеющихся в современной игре, а также аудио двигатели, некоторые комбинации, обработки и фильтрации задач, которые встречаются в современных аудио приложениях. Далее следует постепенное введение в использование этого мощного API.

Приступая к работе с AudioContext

AudioContext для управления и воспроизведения всех звуков. Для получения звука с помощью аудио WEB API, необходимо создать один или несколько источников звука и подключить их к звуку назначения с помощью AudioContext. Эта связь не должна быть прямой, и может пройти через любое число промежуточных AudioNodes, которые действуют как переработка модулей для звукового сигнала. Этот маршрут будет более подробно описан в спецификации Web Audio.

Один экземпляр AudioContext поддерживает несколько входов звука и сложную аудио структуру. И из них будет необходим только один для каждого аудио приложения, которое мы будем создавать.

Cледующий фрагмент создает AudioContext:

var context;
window.addEventListener('load', init, false);
function init() {
   try {
     context = new webkitAudioContext();
  }
   catch(e) {
     alert('Web Audio API is not supported in this browser');
   }
}

Для WebKit-браузеров, используя префикс WebKit, как и webkitAudioContext.Существует таже много интересных аудио WEB API функций, таких как создание AudioNodes и декодирование аудио-данных файлов методом AudioContext.

Загрузка звуков

Следует отметить одну особенность всех WEB-API. При использовании данной технологии обычно передаются пакеты данных, упакованные в форматы “XML”,”JSON” и другие. Поэтому, для полного понимания сути подключения и работы механизма API, необходимо изучить основы. В этом случае можно будет с легкостью использовать любые внешние API, а также создавать свои API, которые в дальнейшем могут работать на благо собственного ресурса./p>

Web Audio API использует AudioBuffer для коротких и средних по длине звуков. Основной подход заключается в использовании XMLHttpRequest для извлечения звуковых файлов. API поддерживает загрузку аудио файлов данных в различных форматах, таких как WAV, MP3, AAC, OGG и другие. Поддержка браузеров для различных аудио-форматов меняется.

Следующий фрагмент демонстрирует загрузки звуковых образцов:

var dogBarkingBuffer = null;
var context = new webkitAudioContext();

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

// Decode asynchronously
request.onload = function() {
   context.decodeAudioData(request.response, function(buffer) {
     dogBarkingBuffer = buffer;
    }, onError);
}
  request.send();
}

Двоичный аудио файл данных, поэтому мы устанавливаем responseType. Для получения дополнительной информации о ArrayBuffers, см. эту статью о XHR2.

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

Когда decodeAudioData () закончится, он вызывает функцию обратного вызова, которая обеспечивает декодированный PCM аудио данных AudioBuffer.

Воспроизведение звуков

После того, как один или несколько AudioBuffers были загружены, то мы готовы для воспроизведения звуков. Давайте предположим, что мы только что загрузили AudioBuffer со звуком «лай собаки» и, что загрузка завершена. Тогда мы можем воспроизвести звуковой файл следующим кодом.

var context = new webkitAudioContext();

 function playSound(buffer) {
   var source = context.createBufferSource();
   source.buffer = buffer;
   source.connect(context.destination);
  source.noteOn(0);
 }

Функция PlaySound () вызывается каждый раз, когда кто-то нажимает клавишу или кликает с помощью мыши.

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

Абстрагирование Web Audio API

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

Ниже приведен пример того, как Вы можете использовать BufferLoader класс. Давайте создадим два AudioBuffers, и, как только они будут загружены, давайте воспроизводить их в одно и то же время.

window.onload = init;
var context;
var bufferLoader;

function init() {
   context = new webkitAudioContext();

   bufferLoader = new BufferLoader(
     context,
       [
         '../sounds/hyper-reality/br-jam-loop.wav',
         '../sounds/hyper-reality/laughter.wav',
      ],
    finishedLoading
   );

   bufferLoader.load();
}

function finishedLoading(bufferList) {
   // Create two sources and play them both together.
   var source1 = context.createBufferSource();
   var source2 = context.createBufferSource();
   source1.buffer = bufferList[0];
   source2.buffer = bufferList[1];

   source1.connect(context.destination);
   source2.connect(context.destination);
   source1.noteOn(0);
   source2.noteOn(0);
}

Работа со временем: воспроизведения звуков с ритмом

Web Audio API позволяет разработчикам точно планировать время воспроизведения. Чтобы продемонстрировать это, давайте создадим простой ритм-трек. Вероятно, наиболее известный ритмический рисунок:

Рис.1 – Ритмический рисунок.

Здесь hat играется восьмыми нотами, и удар, который играется на каждую четверть. Размер 4/4.Предположим, мы загрузили удар, малый и hihat буферы. Далее приведен следующий код:


 for (var bar = 0; bar < 2; bar++) {
   var time = startTime + bar * 8 * eighthNoteTime;
     // Play the bass (kick) drum on beats 1, 5
     playSound(kick, time);
     playSound(kick, time + 4 * eighthNoteTime);

     // Play the snare drum on beats 3, 7
     playSound(snare, time + 2 * eighthNoteTime);
     playSound(snare, time + 6 * eighthNoteTime);

     // Play the hi-hat every eighth note.
   for (var i = 0; i < 8; ++i) {
     playSound(hihat, time + i * eighthNoteTime);
   }
 }

Здесь мы делаем только один повтор вместо неограниченного цикла. Функция PlaySound () играет буфер указанное время, а именно:


 function playSound(buffer, time) {
   var source = context.createBufferSource();
   source.buffer = buffer;
   source.connect(context.destination);
   source.noteOn(time);
 }

Изменение громкости звука

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

Рис.2 – Аудио граф с коэффициентом усиления.

Это соединение установки может быть достигнуто следующим образом:


   var gainNode = context.createGainNode();
   source.connect(gainNode);
   gainNode.connect(context.destination);

После того как граф был создан, можно программно изменять громкость, управляя gainNode.gain.value следующим образом:

gainNode.gain.value = 0.5;

Кросс–затухание между двумя звуками

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

Наглядно это показано на следующей структуре:

Рис.3 – Аудио график с двумя источниками подключенный через усиление узлов.

Чтобы установить это, мы просто создаем два AudioGainNodes и подключенаем каждый источник через узлы, используя что-то вроде этой функции:


 function createSource(buffer) {
   var source = context.createBufferSource();
   // Create a gain node.
   var gainNode = context.createGainNode();
   source.buffer = buffer;
   // Turn on looping.
   source.loop = true;
   // Connectsource to gain.
   source.connect(gainNode);
   // Connect gain to destination.
   gainNode.connect(context.destination);
   
   return {
      source: source,
      gainNode: gainNode
   };
 }

Применение простого звукового фильтра

Рис.4 – Простой звуковой фильтр.

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

 Поддерживаемые типы фильтров включают в себя:

   Фильтр низких частот
   Фильтр верхних частот
   Полосовой фильтр
   Фильтр низкого шельфа
   Фильтр высокого шельфа
   Пиковый фильтр
   Все фильтры

Давайте установим простой фильтр нижних частот для извлечения только низких частот из звукового примера:


 var filter = context.createBiquadFilter();
 source.connect(filter);
 filter.connect(context.destination);
 filter.type = 0; // Low-pass filter. See BiquadFilterNode docs
 filter.frequency.value = 440; // Set cutoff to 440 HZ
 source.noteOn(0);

Наконец, отметим, что пример кода позволяет подключать и отключать фильтр, динамично меняющийся график AudioContext. Мы можем отключить AudioNodes из графика по номеру node.disconnect (outputNumber). Например, чтобы перенаправить граф можно сделать следующее:


 source.disconnect(0);
 filter.disconnect(0);
 source.connect(context.destination);

Дальнейшее прослушивание

Мы рассмотрели основы API, включая загрузку и воспроизведение аудио сэмплов. Мы создали аудио графы с усилением узлов и фильтров, а также запланированных звуков и звуковых настроек параметров, включая некоторые общие звуковые эффекты. На данный момент, вы готовы подключить несколько приложений с классным звуком в Интернете!