Звукові ефекти в JavaScript / HTML5


316

Я використовую HTML5 для програмування ігор; перешкодою, з якою я стикався зараз, є те, як відтворювати звукові ефекти.

Конкретні вимоги малочисельні:

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

Першим моїм підходом було використання <audio>елемента HTML5 та визначення всіх звукових ефектів на моїй сторінці. 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 - дали різні результати. Деякі нічого не грають, а деякі кидають винятки.


Га! Я також переношу стару гру Macintosh в HTML5. Хочете розкрити, кого ви клонуєте?
платний ботанік

1
Це проект ARASHI, буряний клон.
Стефан Кохен

Що розуміється під "змішуванням" звуків?
Mads Skjern

2
Ви закінчили це? Чи можемо ми це побачити?
enyo

4
На жаль, ні. У мене є вміння не закінчувати проекти у вільний час. :( Там в мерзотник репо для нього, але я не чіпали його в роки: github.com/stephank/arashi-js
Stéphan Kochen

Відповіді:


448

AudioОб'єкти HTML5

Вам не потрібно турбуватися з <audio>елементами. HTML 5 дозволяє безпосередньо отримувати доступ до Audioоб'єктів :

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 Audio Audio , який зараз підтримується більшістю браузерів .


18
Audioоб'єкти автобуферовані. Вони розроблені аналогічно Imageоб'єктам, тому методи попереднього завантаження зображень у школі працюють і зі звуком.
Корнель

5
Це також працює на iOS. Зауважте, що вам потрібно використовувати якусь дію користувача (наприклад, натискання на кнопку), щоб ініціювати звук. Ви не можете просто зробити snd.play()на window.load ().
Хаскі

1
Я все ще використовую <audio>тег, оскільки він більш керований. Але все одно дякую за інформацію!
Дерек 朕 會 功夫

2
Я вважаю за краще цей метод, якби не факт, що елементи <audio> html5 дозволяють використовувати декілька джерел, тому якщо браузер не підтримує mp3, ви можете перейти до ogg / wav. Щоб виконати те саме, потрібна хитрість JavaScript.
joelmdev

2
На iOS 6 підтримується автовідтворення: ви можете ініціювати звуки за допомогою простого snd.play () на window.load ().
Pietro Polsinelli

36

WebAudio API від W3C

З липня 2012 року API WebAudio тепер підтримується в Chrome і принаймні частково підтримується у Firefox і планується додавати до IOS станом на 6 версії.

Хоча це достатньо надійний, щоб його програмно використовувати для виконання основних завдань, елемент Audio ніколи не мав на меті забезпечити повну підтримку аудіо для ігор і т.д. тег. Проблема використання тегу Audio для ігор є чимало проблем:

  • Часові прокладки загальні для аудіоелементів
  • Вам потрібен аудіо елемент для кожного примірника звуку
  • Події завантаження поки не є абсолютно надійними
  • Немає загальних регуляторів гучності, немає завмирання, відсутні фільтри / ефекти

Я використав цю статтю Початок роботи з WebAudio, щоб розпочати роботу з API WebAudio. Fieldrunners WebAudio Case Study також добре читати.


Це краща відповідь, ніж прийнята, оскільки вона зосереджена на правильному вирішенні проблеми (WebAudio API), а причини аудіоелементів не є хорошим рішенням, а не намаганням зламати погане рішення з аудіоелементами
Аномалія

29

howler.js

Для створення авторських ігор одним з найкращих рішень є використання бібліотеки, яка вирішує безліч проблем, з якими ми стикаємося при написанні коду для Інтернету, наприклад, howler.js . howler.js резюмує чудовий (але низькорівневий) веб-аудіо 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, генератор ефектів чи відеоігри.


Не можу коментувати розробку ігор, але я використовую це для незначного звукового зворотного зв’язку в інтерфейсі, і для цього він працює абсолютним задоволенням. Швидкий, простий і простий.
Rid Iculous

Дійсно хороший фреймворк, добре працює і в мобільному. Ви повинні запустити це за допомогою сенсорного запуску ... але як тільки це буде зроблено, це виходить з коробки :)
Філіп

9

Ви також можете використовувати це для виявлення аудіо HTML 5 у деяких випадках:

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

Функція виявлення JS HTML 5

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

Дякуємо, що зауважили це. Я дізнався цей метод у has.js, але я вважаю, що він має деякі проблеми в Firefox, і, мабуть, в Opera також відповідно до вихідного коду has.js. (Рефов: github.com/phiggins42/has.js/issues/48 github.com/phiggins42/has.js/blob/master/detect/audio.js#L19 )
Stéphan Kochen

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

Ні. Я не думаю, що створення нового об'єкта для кожного окремого відтворення звуку - це рішення зовсім. Це швидкий і брудний спосіб вирішення, але це можна зробити краще.
Pawel

@ Павель Правда, що це НЕ слід використовувати як основний метод відтворення звуків, але, наскільки мені відомо, принцип у прикладі є єдиним способом відтворення одного і того ж звуку більше, ніж один раз одночасно, або, як це висловив ОП, "перекриваються відтворення". (Не вимагаючи плагінів для браузера.) Моя реальна реалізація в моєму поточному проекті набагато досконаліша, ніж приклад коду, який я розмістив.
F-3000

4

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

Я робив це раніше без елемента HTMLudio <a5> HTML5, використовуючи невеликий об’єкт Flash від http://flash-mp3-player.net/ - я написав музичну вікторину ( http://webdeavour.appspot.com/ ) і використовував його для відтворення музичних кліпів, коли користувач натискав кнопку для запитання. Спочатку у мене був один програвач на запитання, і можна було грати на них один на одного, тому я змінив його, щоб був лише один програвач, який я вказував на різні музичні кліпи.


Це цікава думка - використовувати & audio; елементи як канали. Коли я розміщую два елементи на сторінці, я можу відтворити їх одночасно. Схоже, клонування, яке я роблю, насправді не робить те, що я очікував, тому що в моєму первісному коді також грає два зразки. Тільки не двічі за один зразок. Мені доведеться ще кілька експериментувати з цим, і я повернусь до результатів!
Stéphan Kochen

Так, можливо, є тонка причина, чому його називають клоном, а не копією. Можливо, клон все-таки ділиться чимось із оригіналом, що заважає їм одночасно грати.
Лі Ковальковський

Для довідки повторне використання того ж елемента <audio> не працює, принаймні у Firefox. Ви можете встановити атрибут 'src', але він фактично не завантажує інший зразок.
Стефан Кохен

4

Погляньте на сайт jai (-> дзеркало ) (аудіоінтерфейс javascript). З огляду на їх джерело, схоже, вони дзвонять play()неодноразово, і вони зазначають, що їх бібліотека може бути доречною для використання в іграх на базі HTML5.

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


3

Щоб відтворити один і той же зразок кілька разів, чи не вдалося б зробити щось подібне:

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

( eє аудіоелементом)

Можливо, я повністю неправильно зрозумів вашу проблему, чи хочете, щоб звуковий ефект відтворювався кілька разів одночасно? Тоді це абсолютно неправильно.


Це правильно, мені потрібно відтворювати один і той же зразок кілька разів одночасно.
Stéphan Kochen

Так, це відтворюється один і той же екземпляр кілька разів, але для людей, які дивляться на цю відповідь, просто зауважте, що це не спричиняє "перекриття відтворення", як сказано в ОП.
Патрік Робертс

3

Ось ідея. Завантажте все своє аудіо для певного класу звуків в один окремий аудіоелемент, де дані src - всі ваші зразки в суміжний аудіофайл (напевно, хочете трохи тиші між ними, щоб ви могли захоплювати та вирізати зразки з таймаутом менше ризик кровотечі до наступної проби). Потім зверніться до зразка і розіграйте його, коли потрібно.

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

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



2

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

Це дозволить вам робити все, що завгодно:

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

Сподіваюся, що це допомагає.


ця бібліотека досить приголомшлива, я дійсно копаю генератор sfx. час для веб- завантаження
RozzA

1

Неможливо зробити багатогранні гри з одним <audio>елементом. Для цього потрібно використовувати кілька елементів.


1

Я зіткнувся з цим під час програмування генератора музичних карток. Почав з різних бібліотек, але кожного разу якимось чином виникали збої. Відставання від нормальної реалізації звуку було поганим, без декількох відтворень ... врешті-решт, в кінцевому підсумку використовується низька бібліотека + звуковий диспетчер:

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

Ви можете ознайомитись з реалізацією тут: http://musicbox.grit.it/

Я створив файли wav + ogg для відтворення кількох браузерів. Цей плеєр музичної скриньки працює чуйно на ipad, iphone, Nexus, mac, pc, ... працює для мене.


Це приємне додаток для музичної скриньки! Чи є у вас сховище git? Я можу використовувати його з нашими дітьми!
icarito

0

Я знаю, що це тотальний злом, але подумав, що я повинен додати цей зразок аудіобібліотеки з відкритим кодом, який я поставив на Github деякий час тому ...

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

Після натискання на посилання нижче, наберіть клавіші домашнього рядка, щоб відтворити блюз-риф (також введіть кілька клавіш одночасно тощо)

Зразок за допомогою бібліотеки jThump >> http://davealger.com/apps/jthump/

В основному це працює, створюючи невидимі <iframe>елементи, які завантажують сторінку, яка відтворює звук наReady ().

Це, звичайно, не ідеально, але ви можете поставити +1 для цього рішення лише на основі творчості (а також того, що воно є відкритим кодом та працює в будь-якому браузері, на якому я його пробував). Я сподіваюся, що це дає хоч комусь іншому, що шукає якісь ідеї.

:)


Чому хтось за це проголосував? Мені це здається життєздатним варіантом.
jtrick

це досить гакісне рішення, але я використав цю бібліотеку, щоб зробити зразок html 5 полотняної гри, щоб вона все-таки працювала ... гра з використанням цієї бібліотеки тут - beepbox.net
DaveAlger

0

Вибрана відповідь буде працювати у всьому, крім IE. Я написав підручник про те, як змусити його працювати перехресний браузер = 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

Ви завжди можете спробувати, AudioContextце обмежена підтримка, але це частина робочого проекту веб-аудіо api . Можливо, варто, якщо ви плануєте щось випустити в майбутньому. А якщо ви програмуєте лише на хром та Firefox, ви золоті.


0

var AudioContextFunc = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContextFunc();
var player=new WebAudioFontPlayer();
var instrumVox,instrumApplause;
var drumClap,drumLowTom,drumHighTom,drumSnare,drumKick,drumCrash;
loadDrum(21,function(s){drumClap=s;});
loadDrum(30,function(s){drumLowTom=s;});
loadDrum(50,function(s){drumHighTom=s;});
loadDrum(15,function(s){drumSnare=s;});
loadDrum(5,function(s){drumKick=s;});
loadDrum(70,function(s){drumCrash=s;});
loadInstrument(594,function(s){instrumVox=s;});
loadInstrument(1367,function(s){instrumApplause=s;});
function loadDrum(n,callback){
  var info=player.loader.drumInfo(n);
  player.loader.startLoad(audioContext, info.url, info.variable);
  player.loader.waitLoad(function () {callback(window[info.variable])});
}
function loadInstrument(n,callback){
  var info=player.loader.instrumentInfo(n);
  player.loader.startLoad(audioContext, info.url, info.variable);
  player.loader.waitLoad(function () {callback(window[info.variable])});
}
function uhoh(){
  var when=audioContext.currentTime;
  var b=0.1;
  player.queueWaveTable(audioContext, audioContext.destination, instrumVox, when+b*0, 60, b*1);
  player.queueWaveTable(audioContext, audioContext.destination, instrumVox, when+b*3, 56, b*4);
}
function applause(){
  player.queueWaveTable(audioContext, audioContext.destination, instrumApplause, audioContext.currentTime, 54, 3);
}
function badumtss(){
  var when=audioContext.currentTime;
  var b=0.11;
  player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*0, drumSnare.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumLowTom, when+b*0, drumLowTom.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*1, drumSnare.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumHighTom, when+b*1, drumHighTom.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumSnare, when+b*3, drumSnare.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumKick, when+b*3, drumKick.zones[0].keyRangeLow, 3.5);
  player.queueWaveTable(audioContext, audioContext.destination, drumCrash, when+b*3, drumCrash.zones[0].keyRangeLow, 3.5);
}
<script src='https://surikov.github.io/webaudiofont/npm/dist/WebAudioFontPlayer.js'></script>
<button onclick='badumtss();'>badumtss</button>
<button onclick='uhoh();'>uhoh</button>
<button onclick='applause();'>applause</button>
<br/><a href='https://github.com/surikov/webaudiofont'>More sounds</a>


0

API веб-аудіо є правильним інструментом для цієї роботи. Робота з завантаженням звукових файлів та їх відтворенням небагато. На щастя, там є багато бібліотек, які спрощують роботу. Цікавившись звуками, я також створив бібліотеку під назвою musquito яку ви також можете перевірити.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.