Звуковые эффекты в JavaScript / HTML5

280

Я использую HTML5 для программирования игр; препятствие, с которым я столкнулся сейчас, - это как воспроизвести звуковые эффекты.

Конкретные требования немногочисленны:

  • Воспроизведение и смешивание нескольких звуков,
  • Воспроизведение одного и того же образца несколько раз, возможно перекрытие воспроизведения,
  • Прерывание воспроизведения образца в любой точке,
  • Желательно воспроизводить файлы WAV, содержащие (низкокачественные) raw PCM, но я могу их преобразовать, конечно.

Мой первый подход состоял в том, чтобы использовать элемент HTML5 <audio> и определять все звуковые эффекты на моей странице. Firefox воспроизводит файлы WAV просто персиковые, но вызов #play несколько раз не воспроизводит образец несколько раз. Из моего понимания спецификации HTML5 элемент <audio> также отслеживает состояние воспроизведения, поэтому это объясняет.

Я сразу подумал, что нужно клонировать аудио элементы, поэтому я создал следующую крошечную библиотеку JavaScript, чтобы сделать это для меня (зависит от jQuery):

var Snd = {
  init: function() {
    $("audio").each(function() {
      var src = this.getAttribute('src');
      if (src.substring(0, 4) !== "snd/") { return; }
      // Cut out the basename (strip directory and extension)
      var name = src.substring(4, src.length - 4);
      // Create the helper function, which clones the audio object and plays it
      var Constructor = function() {};
      Constructor.prototype = this;
      Snd[name] = function() {
        var clone = new Constructor();
        clone.play();
        // Return the cloned element, so the caller can interrupt the sound effect
        return clone;
      };
    });
  }
};

Итак, теперь я могу сделать Snd.boom(); с консоли Firebug и воспроизвести snd/boom.wav, но я все еще не могу воспроизвести один и тот же образец несколько раз. Похоже, что элемент <audio> - это скорее больше потоковая функция, чем нечто, для воспроизведения звуковых эффектов.

Есть ли умный способ сделать это, что я пропал без вести, желательно используя только HTML5 и JavaScript?

Я также должен отметить, что моя тестовая среда - Firefox 3.5 на Ubuntu 9.10. Другие браузеры, которые я пробовал - Opera, Midori, Chromium, Epiphany - произвели разные результаты. Некоторые не играют ничего, а некоторые бросают исключения.

  • 0
    Хах! Я также портирую старую игру для Macintosh на HTML5. Хотите раскрыть, кого вы клонируете?
  • 1
    Это проект ARASHI, бурный клон.
Показать ещё 4 комментария
Теги:

17 ответов

400
Лучший ответ

HTML5 Audio объекты

Вам не нужно беспокоиться о элементах <audio>. HTML 5 позволяет напрямую обращаться к Audio objects:

var snd = new Audio("file.wav"); // buffers automatically when created
snd.play();

Нет поддержки для смешивания в текущей версии спецификации.

Чтобы воспроизвести один и тот же звук несколько раз, создайте несколько экземпляров объекта Audio. Вы также можете установить snd.currentTime=0 на объект после завершения воспроизведения.


Поскольку конструктор JS не поддерживает резервные элементы <source>, вы должны использовать

(new Audio()).canPlayType("audio/ogg; codecs=vorbis")

чтобы проверить, поддерживает ли браузер Ogg Vorbis.


Если вы пишете игру или музыкальное приложение (больше, чем просто плеер), вы захотите использовать более продвинутый API веб-аудио, который теперь поддерживается большинством браузеров.

  • 0
    Это именно то, что я делаю сейчас, спасибо за указатель! Я все еще использую элементы <audio>, потому что они позволяют мне: а) автобуферировать и б) по-прежнему указывать все ресурсы на странице HTML. Я просто прочитал их атрибуты 'src', как прежде, чтобы создать экземпляр Audio. Firebug не показывает никаких дополнительных запросов, поэтому кеш работает, и все замечательно!
  • 17
    Audio объекты автоматически буферизируются. Они разработаны аналогично объектам Image , поэтому методы предварительной загрузки изображений oldschool работают и со звуком.
Показать ещё 14 комментариев
31

API WebAudio по W3C

По состоянию на июль 2012 года API WebAudio теперь поддерживается в Chrome и, по крайней мере, частично поддерживается в Firefox, и предполагается, что он будет добавлен в IOS с версии 6.

Несмотря на то, что он достаточно прост, чтобы программно использоваться для основных задач, элемент Audio никогда не предназначался для полной поддержки аудио игр и т.д. Он был разработан, чтобы позволить единый кусок носителя быть встроенным в страницу, аналогичную к тегу img. Существует множество проблем с попыткой использовать тег Audio для игр:

  • Временные пропуски являются общими для аудиоэлементов.
  • Для каждого экземпляра звука вам нужен элемент Audio
  • События загрузки не являются полностью надежными, но
  • Нет общих регуляторов громкости, без затухания, нет фильтров/эффектов

Я использовал эту Начало работы с WebAudio, чтобы начать работу с API WebAudio. FieldRunners WebAudio Case Study также хорошо читается.

  • 0
    Хорошие статьи, спасибо!
20

howler.js

Для разработки игр одним из лучших решений является использование библиотеки, которая решает многие проблемы, с которыми мы сталкиваемся при написании кода для Интернета, например howler.js., howler.js абстрагирует большой (но низкоуровневый) Web Audio API в простой в использовании фреймворк. Он попытается вернуться к HTML5 Audio Element, если API веб-аудио недоступен.

var sound = new Howl({
  urls: ['sound.mp3', 'sound.ogg']
}).play();
// it also provides calls for spatial/3d audio effects (most browsers)
sound.pos3d(0.1,0.3,0.5);

wad.js

Другая отличная библиотека wad.js, которая особенно полезна для создания синтезаторного звука, такого как музыка и эффекты. Например:

var saw = new Wad({source : 'sawtooth'})
saw.play({
    volume  : 0.8,
    wait    : 0,     // Time in seconds between calling play() and actually triggering the note.
    loop    : false, // This overrides the value for loop on the constructor, if it was set. 
    pitch   : 'A4',  // A4 is 440 hertz.
    label   : 'A',   // A label that identifies this note.
    env     : {hold : 9001},
    panning : [1, -1, 10],
    filter  : {frequency : 900},
    delay   : {delayTime : .8}
})

Звук для игр

Другая библиотека, похожая на Wad.js, это "Звук для игр ", она больше ориентирована на производство эффектов, предоставляя аналогичный набор функций через относительно разные (и, возможно, более сжатые ощущения) API:

function shootSound() {
  soundEffect(
    1046.5,           //frequency
    0,                //attack
    0.3,              //decay
    "sawtooth",       //waveform
    1,                //Volume
    -0.8,             //pan
    0,                //wait before playing
    1200,             //pitch bend amount
    false,            //reverse bend
    0,                //random pitch range
    25,               //dissonance
    [0.2, 0.2, 2000], //echo array: [delay, feedback, filter]
    undefined         //reverb array: [duration, decay, reverse?]
  );
}

Резюме

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

  • 0
    Не могу комментировать разработку игры, но я использую это для некоторой незначительной звуковой обратной связи в интерфейсе, и для этого это работает абсолютное удовольствие. Быстро, легко и просто.
  • 0
    Действительно хороший фреймворк, хорошо работает и в мобильном телефоне. Вы должны запустить его с помощью Touchstart ... но как только это будет сделано, это работает из коробки :)
9

Вы также можете использовать это для обнаружения аудио HTML 5 в некоторых случаях:

http://diveintohtml5.ep.io/everything.html

HTML 5 Функция обнаружения JS

function supportsAudio()
{
    var a = document.createElement('audio'); 
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
}
5

Здесь один из способов, позволяющих одновременно воспроизводить один и тот же звук. Комбинируйте с предварительным загрузчиком, и все готово. Это, по крайней мере, работает с Firefox 17.0.1, еще не проверил его ни с чем.

// collection of sounds that are playing
var playing={};
// collection of sounds
var sounds={step:"knock.ogg",throw:"swing.ogg"};

// function that is used to play sounds
function player(x)
{
    var a,b;
    b=new Date();
    a=x+b.getTime();
    playing[a]=new Audio(sounds[x]);
    // with this we prevent playing-object from becoming a memory-monster:
    playing[a].onended=function(){delete playing[a]};
    playing[a].play();
}

Привяжите это к клавише клавиатуры и наслаждайтесь:

player("step");
  • 0
    Нет. Я не думаю, что создание нового объекта для каждого отдельного воспроизведения звука - это вообще решение. Это быстрый и грязный обходной путь, но это можно сделать лучше.
  • 0
    @Pawel Правда, это НЕ должно использоваться в качестве основного метода воспроизведения звуков, но, насколько мне известно, принцип в примере - это единственный способ воспроизводить один и тот же звук более одного раза одновременно, или, как выразился OP, "перекрывающиеся воспроизведения". (Не требуя плагинов для браузера.) Моя фактическая реализация в моем текущем проекте намного сложнее, чем пример кода, который я разместил.
4

Похоже, что вы хотите многоканальные звуки. Предположим, что у вас есть 4 канала (например, в действительно старых 16-разрядных играх), пока я еще не играл с аудиофункцией HTML5, но вам просто не нужно 4 <audio> элементы и цикл, который используется для воспроизведения следующего звукового эффекта? Вы пробовали это? Что происходит? Если это работает: Чтобы воспроизводить больше звуков одновременно, просто добавьте больше <audio> элементы.

Я сделал это раньше без HTML5 <audio> элемент, используя небольшой Flash-объект из http://flash-mp3-player.net/ - я написал музыкальную викторину (http://webdeavour.appspot.com/) и использовал его для воспроизведения клипов музыки, когда пользователь нажал кнопку для вопроса. Первоначально у меня был один игрок на вопрос, и можно было сыграть их поверх всех друг друга, поэтому я изменил его, так что был только один игрок, который я указал на разные клипы.

  • 0
    Это интересная мысль, чтобы использовать & lt; audio & gt; элементы как каналы. Когда я размещаю два элемента на странице, я могу воспроизводить их одновременно. Похоже, что клонирование, которое я делаю, на самом деле не делает то, что я ожидаю, потому что в моем исходном коде воспроизведение двух примеров также работает. Просто не дважды один и тот же образец. Мне придется еще поэкспериментировать с этим, и я вернусь к результатам!
  • 0
    Да, возможно, есть тонкая причина, почему она называется клоном, а не копией. Возможно, клон все еще делится чем-то с оригиналом, что мешает им играть одновременно.
Показать ещё 1 комментарий
4

Посмотрите jai (- > mirror) (javascript audio interface). От взгляда на их источник они, как представляется, многократно звонят play(), и они отмечают, что их библиотека может быть подходящей для использования в играх на базе HTML5.

Вы можете запускать несколько звуковых событий одновременно, которые могут быть использованы для создания Javascript-игр или имея голос, говорящий над некоторыми фоновая музыка

  • 1
    Эта ссылка не работает для меня, но это работает: bocoup.com/open-source/jai
  • 2
    новая ссылка тоже больше не работает
3

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

Если вам нужно больше одного из них, вы можете создать дополнительный аудиоэлемент с тем же src, чтобы он был кэширован. Теперь у вас есть несколько "треков". Вы можете использовать группы треков с вашей любимой схемой выделения ресурсов, например Round Robin и т.д.

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

  • 1
    Кто-нибудь пробовал это с многообещающими результатами?
3

Чтобы воспроизвести один и тот же образец несколько раз, не было бы возможным сделать что-то вроде этого:

e.pause(); // Perhaps optional
e.currentTime = 0;
e.play();

(e - это аудио-элемент)

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

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

Я бы рекомендовал использовать SoundJS, библиотеку, с которой я помогаю. Это позволяет вам писать единую базу кода, которая работает повсеместно, с использованием SoundJS для веб-аудио, html-аудио или флеш-аудио.

Это позволит вам сделать все, что вам нужно:

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

Надеюсь, что это поможет.

  • 0
    эта библиотека довольно крутая, я действительно копаю генератор sfx. время сделать веб сайко скачать для всех желающих
2

http://robert.ocallahan.org/2011/11/latency-of-html5-sounds.html

http://people.mozilla.org/~roc/audio-latency-repeating.html

Работает нормально в Firefox и Chrome для меня.

Чтобы остановить звук, который вы начали, выполните   var sound = document.getElementById( "shot" ). cloneNode (true);   sound.play(); и позже   sound.pause();

1

Я столкнулся с этим при программировании генератора карт музыкальных карт. Начались с разных библиотек, но каждый раз возникал сбой. Задержка в нормальной реализации звука была плохая, не было многократных игр... в конечном итоге закончилась использование библиотеки lowlag + soundmanager:

http://lowlag.alienbill.com/ а также http://www.schillmania.com/projects/soundmanager2/

Вы можете проверить реализацию здесь: http://musicbox.grit.it/

Я создал wav + ogg файлы для нескольких браузеров. Этот проигрыватель музыки работает с учетом ipad, iphone, Nexus, mac, pc,... работает для меня.

  • 0
    Это хорошее приложение для музыкальной шкатулки! У вас есть git-репозиторий? Я мог бы использовать это с нашими детьми!
1

Невозможно выполнить многократное воспроизведение с помощью одного элемента <audio>. Для этого вам нужно использовать несколько элементов.

0

Вы всегда можете попробовать AudioContext, у него ограниченная поддержка, но это часть веб-аудио api рабочий проект. Возможно, это будет стоить того, если вы планируете выпускать что-то в будущем. И если вы только программируете на Chrome и Firefox, вы золотые.

0

Выбранный ответ будет работать во всем, кроме IE. Я написал учебник о том, как заставить его работать cross browser = http://www.andy-howard.com/how-to-play-sounds-cross-browser-including-ie/index.html

Вот функция, которую я написал:

function playSomeSounds(soundPath)
 {

 var trident = !!navigator.userAgent.match(/Trident\/7.0/);
 var net = !!navigator.userAgent.match(/.NET4.0E/);
 var IE11 = trident && net
 var IEold = ( navigator.userAgent.match(/MSIE/i) ? true : false );
 if(IE11 || IEold){
 document.all.sound.src = soundPath;
 }
 else
 {
 var snd = new Audio(soundPath); // buffers automatically when created
 snd.play();
 }
 };

Вам также нужно добавить следующий тег на страницу html:

<bgsound id="sound">

Наконец, вы можете вызвать функцию и просто пройти по пути здесь:

playSomeSounds("sounds/welcome.wav");
0

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

https://github.com/run-time/jThump

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

Пример с использованием библиотеки jThump → http://davealger.com/apps/jthump/

В основном он работает, создавая невидимые элементы <iframe>, которые загружают страницу, воспроизводящую звук onReady().

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

:)

  • 0
    Почему кто-то это проголосовал? Похоже, жизнеспособный вариант для меня.
  • 0
    это довольно хакерское решение, но я использовал эту библиотеку для создания примера игры на холсте html 5, чтобы она могла работать, тем не менее ... игра с этой библиотекой здесь - beepbox.net
0

Для самой широкой совместимости я бы рекомендовал использовать небольшой FLASH-объект, который может взаимодействовать с Javascript. Это намного проще, чем пытаться использовать элемент audio в HTML5 из-за текущей (и не будущей) поддержки.

проверьте этот проект в качестве примера: http://www.schillmania.com/projects/soundmanager/ текущая и расширенная версия: http://www.schillmania.com/projects/soundmanager2/

Ещё вопросы

Сообщество Overcoder
Наверх
Меню