JavaScript / HTML5'te ses efektleri


316

Oyunları programlamak için HTML5 kullanıyorum; şu an karşılaştığım engel ses efektlerinin nasıl çalınacağı.

Özel gereksinimlerin sayısı azdır:

  • Birden fazla ses çalın ve karıştırın,
  • Aynı örneği birden çok kez oynatın, muhtemelen çakışan oynatmalar,
  • Bir numunenin herhangi bir noktada çalınmasına ara verin,
  • Tercihen (düşük kaliteli) ham PCM içeren WAV dosyalarını oynatın, ancak elbette bunları dönüştürebilirim.

İlk yaklaşım HTML5 <audio>öğesini kullanmak ve sayfamdaki tüm ses efektlerini tanımlamaktı. Firefox, WAV dosyalarını sadece şeftali gibi oynatır, ancak #playbirden çok kez çağırmak , örneği çok kez çalmaz. HTML5 spesifikasyonunu anladığımdan, <audio>öğe oynatma durumunu da izler, böylece nedenini açıklar.

Benim acil düşüncem ses öğelerini klonlamak oldu, bu yüzden benim için bunu yapmak için aşağıdaki küçük JavaScript kitaplığı oluşturdum (jQuery bağlıdır):

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

Şimdi Snd.boom();Firebug konsolundan yapabilir ve oynayabilirim snd/boom.wav, ancak yine de aynı örneği birden çok kez çalamıyorum. O görünüyor <audio>eleman yerine ses efektleri oynamak için bir şey gerçekten daha fazla bir akış özelliği taşımaktadır.

Tercihen yalnızca HTML5 ve JavaScript kullanarak bunu kaçırmamı sağlamanın akıllıca bir yolu var mı?

Şunu da belirtmeliyim ki, test ortamım Ubuntu 9.10 üzerinde Firefox 3.5. Denediğim diğer tarayıcılar - Opera, Midori, Chromium, Epiphany - çeşitli sonuçlar üretti. Bazıları hiçbir şey oynamaz, bazıları da istisna atar.


Hah! Ayrıca eski bir Macintosh oyununu HTML5'e taşıyorum. Hangisini klonladığınızı açıklamak ister misiniz?
ücretli bir inek

1
Bu proje ARASHI, fırtınalı bir klon.
Stéphan Kochen

Sesleri “karıştırmak” ile kastedilen nedir?
Mads Skjern

2
Bitirdin mi Görebilir miyiz?
enyo

4
Üzgünüm hayır. Boş zaman projelerini bitiremediğim için bir yeteneğim var. :( Bunun için bir git repo var, ama yıllar içinde dokunmadım: github.com/stephank/arashi-js
Stéphan Kochen

Yanıtlar:


448

HTML5 Audionesneleri

<audio>Elementlerle uğraşmanıza gerek yok . HTML 5, Audionesnelere doğrudan erişmenizi sağlar :

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

Spesifikasyonun mevcut sürümünde karıştırma için destek yoktur.

Aynı sesi birden çok kez çalmak için Audionesnenin birden çok örneğini oluşturun . snd.currentTime=0Nesneyi oynatmayı bitirdikten sonra da ayarlayabilirsiniz .


JS yapıcısı yedek <source>öğeleri desteklemediğinden ,

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

tarayıcının Ogg Vorbis'i destekleyip desteklemediğini test etmek için.


Bir oyun veya müzik uygulaması (yalnızca bir oynatıcıdan daha fazlası) yazıyorsanız , şu anda daha gelişmiş Web Audio API'sını kullanmak istersiniz. çoğu tarayıcı tarafından desteklenen .


18
Audionesneler otomatik olarak karıştırılır. ImageNesnelere benzer şekilde tasarlandıklarından , eski okul görüntü önyükleme teknikleri de sesle çalışır.
Kornel

5
Bu, iOS'ta da çalışır. Bunu gerçi Not ihtiyaç kullanıcı eylemi çeşit kullanmak (örneğin bir düğme tıklama) sesi başlatmak için. Sadece snd.play()window.load () üzerinde bir şey yapamazsınız .
Husky

1
<audio>Daha kontrol edilebilir olduğundan etiketi hala kullanıyorum . Ama yine de bilgi için teşekkürler!
Derek 朕 會 功夫

2
<audio> html5 öğelerinin birden fazla kaynağa izin vermesi olmasaydı bu yöntemi tercih ederim, bu yüzden bir tarayıcı mp3'ü desteklemiyorsa, ogg / wav'a geri dönebilirsiniz. Aynı şeyi başarmak için javascriptte bir numara gerekir.
joelmdev

2
İOS 6'da otomatik oynatma desteklenir: window.load () üzerinde basit bir snd.play () ile ses başlatabilirsiniz.
Pietro Polsinelli

36

W3C'den WebAudio API'sı

Temmuz 2012 itibariyle, WebAudio API'sı artık Chrome'da destekleniyor ve en azından kısmen Firefox'ta destekleniyor ve sürüm 6'dan itibaren IOS'a eklenmesi planlanıyor.

Temel görevler için programlı olarak kullanılacak kadar sağlam olmasına rağmen, Ses öğesi hiçbir zaman oyunlar için tam ses desteği sağlamak için tasarlanmamıştı, vb. etiket. Oyunlar için Ses etiketini kullanmaya çalışırken bir çok sorun var:

  • Zamanlama fişleri Ses öğeleriyle ortaktır
  • Bir sesin her örneği için bir Ses öğesine ihtiyacınız var
  • Yükleme olayları henüz tamamen güvenilir değil
  • Ortak ses kontrolü yok, solma yok, filtre / efekt yok

Bu WebAudio API'sini kullanmaya başlamak için WebAudio ile Başlarken makalesini kullandım. Fieldrunners WebAudio Vaka Çalışması de iyi bir okuma.


Sorunun doğru çözümüne (WebAudio API) odaklandığından ve Ses öğelerinin Ses öğeleriyle kötü bir çözümü bir araya getirmeye çalışmaktan ziyade Ses öğelerinin iyi bir çözüm olmadığından, bu kabul edilen yanıttan daha iyi bir yanıttır
Anomali

29

howler.js

Oyun geliştirme için en iyi çözümlerden biri, howler.js gibi web için kod yazarken karşılaştığımız birçok sorunu çözen bir kitaplık kullanmaktır . howler.js harika (ancak düşük seviyeli) Web Audio API'sını kullanımı kolay bir çerçeveye özetler . Web Ses API'sı kullanılamıyorsa HTML5 Ses Öğesine geri dönmeye çalışacaktır .

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

Başka bir harika kütüphane, özellikle müzik ve efektler gibi synth ses üretmek için yararlı olan wad.js'dir . Örneğin:

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}
})

Oyunlar için Ses

Wad.js'ye benzer başka bir kütüphane " Oyunlar için Ses " dir, efekt üretimine daha fazla odaklanırken, nispeten farklı (ve belki de daha özlü bir his) API ile benzer bir işlevsellik seti sağlar:

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?]
  );
}

özet

İster tek bir ses dosyasını çalın, ister kendi html tabanlı müzik düzenleyicinizi, efekt oluşturucunuzu veya video oyununuzu yaratın, bu kütüphanelerin her biri bir göz atmaya değer.


Oyun geliştirme hakkında yorum yapamıyorum, ancak bunu bir arayüzdeki bazı küçük sesli geri bildirimler için kullanıyorum ve bunun için mutlak bir muamele çalışıyor. Hızlı, kolay ve basit.
Rid Iculous

Gerçekten güzel bir çerçeve, mobil de güzel çalışıyor. Touchstart ile tetiklemelisiniz ... ama bir kez bittiğinde kutudan çıkar :)
Philip

9

Bazı durumlarda HTML 5 sesini algılamak için bunu da kullanmak isteyebilirsiniz:

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

HTML 5 JS Tespit fonksiyonu

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

Bunu not ettiğiniz için teşekkürler. Bu yöntemi has.js'den öğrendim, ancak has.js kaynak koduna göre Firefox'ta ve görünüşe göre Opera'da bazı sorunlar olduğunu düşünüyorum. (refs: github.com/phiggins42/has.js/issues/48 github.com/phiggins42/has.js/blob/master/detect/audio.js#L19 )
Stéphan Kochen

5

İşte aynı sesi bile aynı anda çalmayı mümkün kılmak için bir yöntem. Ön yükleyici ile birleştirin ve hazırsınız. Bu en azından Firefox 17.0.1 ile çalışıyor, henüz başka bir şeyle test etmedim.

// 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();
}

Bunu bir klavye anahtarına bağlayın ve keyfini çıkarın:

player("step");

Hayır. Her ses çalması için yeni bir nesne oluşturmanın hiç de bir çözüm olduğunu düşünmüyorum. Hızlı ve kirli bir çözüm, ancak bu daha iyi yapılabilir.
Pawel

@Pawel Doğru, bunun ses çalmanın ana yöntemi olarak KULLANILMAMASI gerektiğini, ancak bildiğim kadarıyla, örnekteki prensip aynı sesi aynı anda birden fazla çalmanın tek yolu veya OP'nin ifade ettiği gibi, msgstr "örtüşen oynatmalar". (Tarayıcı eklentileri gerektirmeden.) Şu anki projemdeki gerçek uygulamam, gönderdiğim örnek koddan çok daha karmaşık.
F-3000

4

İstediğiniz gibi çok kanallı sesler geliyor. Diyelim ki 4 kanalınız var (gerçekten eski 16 bit oyunlarda olduğu gibi), henüz HTML5 ses özelliğiyle oynamaya henüz sahip değilim, ancak sadece 4 <audio> öğeye ve kullanılan döngüye ihtiyacınız yok sonraki ses efekti oynamak için? Bunu denedin mi? Ne oluyor? Çalışıyorsa: Aynı anda daha fazla ses çalmak için daha fazla <audio> öğe ekleyin.

Bunu daha önce HTML5 <audio> öğesi olmadan, http://flash-mp3-player.net/ adresinden küçük bir Flash nesnesi kullanarak yaptım - Bir müzik sınavı yazdım ( http://webdeavour.appspot.com/ ) ve kullanıcı soru düğmesini tıkladığında müzik kliplerini çalmak için kullandı. Başlangıçta soru başına bir oyuncum vardı ve bunları üst üste çalmak mümkün oldu, bu yüzden değiştirdim, böylece farklı müzik kliplerine işaret ettiğim sadece bir oyuncu vardı.


Bu ilginç bir düşünce, & lt; audio & gt; kanal olarak elemanlar. Bir sayfada iki öğeyi koymak, ben yapabilirsiniz aynı anda oynarlar. Yaptığım klonlama aslında beklediğim şeyi yapmıyor gibi görünüyor, çünkü orijinal kodumda iki örnek oynamak da işe yarıyor. Aynı numunenin iki katı değil. Bunu biraz daha denemek zorundayım ve sonuçlara geri döneceğim!
Stéphan Kochen

Evet, muhtemelen klon olarak adlandırılmasının ve kopyalanmamasının ince bir nedeni var. Belki de klon, her ikisinin aynı anda oynamasını engelleyen orijinal ile hala bir şeyler paylaşıyor.
Lee Kowalkowski

Referans olarak, en azından Firefox'ta aynı <audio> öğesinin yeniden kullanılması işe yaramaz. 'Src' özniteliğini ayarlayabilirsiniz, ancak aslında farklı bir örnek yüklemez.
Stéphan Kochen

4

Göz at jai (-> ayna ) (javascript ses arayüzü) sitede. Kaynaklarına baktığından play()tekrar tekrar aradıkları görülüyor ve kütüphanelerinin HTML5 tabanlı oyunlarda kullanım için uygun olabileceğinden bahsediyorlar.

Javascript oyunları oluşturmak veya arka plan müziği üzerinden sesli konuşma yapmak için kullanılabilecek birden fazla ses olayını aynı anda tetikleyebilirsiniz.


3

Aynı örneği birden çok kez çalmak için, böyle bir şey yapmak mümkün olmaz mı:

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

( eses öğesidir)

Belki probleminizi tamamen yanlış anladım, ses efektinin aynı anda birden fazla çalmasını ister misiniz? O zaman bu tamamen yanlış.


Bu doğru, aynı örnek aynı anda birden çok kez oynamak gerekir.
Stéphan Kochen

Evet, bu aynı örneği birden çok kez oynatır, ancak bu cevaba bakan insanlar için, bunun OP kelimesi ile "örtüşen oynatmaya" neden olmadığını unutmayın.
Patrick Roberts

3

İşte bir fikir. Belirli bir ses sınıfı için tüm seslerinizi, src verilerinin bitişik bir ses dosyasındaki tüm örnekleriniz olduğu tek bir ses öğesine yükleyin (muhtemelen daha az bir zaman aşımı ile örnekleri yakalayıp kesebilirsiniz sonraki numuneye kanama riski). Ardından, numuneyi arayın ve gerektiğinde çalın.

Oynatmak için bunlardan birden fazlasına ihtiyacınız varsa, önbelleğe alınması için aynı src'ye sahip ek bir ses öğesi oluşturabilirsiniz. Artık etkili bir şekilde birden fazla “parçanız” var. Round Robin vb. Gibi favori kaynak ayırma şemanızla parça gruplarını kullanabilirsiniz.

Ayrıca, kaynak kullanılabilir hale geldiğinde çalınacak sesleri parçaya sıralamak veya çalmakta olan bir örneği kesmek gibi diğer seçenekleri de belirtebilirsiniz.



2

Geliştirilmesine yardım ettiğim bir kütüphane olan SoundJS'i kullanmanızı tavsiye ederim . SoundJS, web sesi, html ses veya flash sesi uygun şekilde seçerek her yerde çalışan tek bir kod tabanı yazmanıza olanak tanır.

İstediğiniz her şeyi yapmanıza izin verecektir:

  • Birden fazla ses çalın ve karıştırın,
  • Aynı örneği birden çok kez oynatın, muhtemelen çakışan oynatmalar
  • Bir numunenin herhangi bir noktada kesilmesi
  • içeren WAV dosyalarını oynat (tarayıcı desteğine bağlı olarak)

Umarım yardımcı olur.


Bu kütüphane oldukça harika, gerçekten sfx jeneratör kazmak. ilgilenen herkes
RozzA

1

Tek bir <audio>elemanla çoklu çekim yapmak mümkün değildir . Bunun için birden fazla öğe kullanmanız gerekir.


1

Bir müzik kutusu kart üreteci programlarken bununla karşılaştım. Farklı kütüphanelerle başladı ama her seferinde bir aksaklık vardı. Normal ses uygulamasındaki gecikme kötüydü, çoklu çalma yok ... sonunda lowlag kütüphanesi + soundmanager kullanılarak sona erdi:

http://lowlag.alienbill.com/ ve http://www.schillmania.com/projects/soundmanager2/

Uygulamayı buradan kontrol edebilirsiniz: http://musicbox.grit.it/

Çoklu tarayıcı oyunları için wav + ogg dosyaları oluşturdum. Bu müzik kutusu çalar ipad, iphone, Nexus, mac, pc, ... üzerinde çalışıyor benim için çalışıyor.


Güzel bir müzik kutusu uygulaması! Git deponuz var mı? Çocuklarımızla kullanabilirim!
icarito

0

Bunun toplam bir hack olduğunu biliyorum ama bir süre önce github'a koyduğum bu örnek açık kaynaklı ses kütüphanesini eklemeliyim diye düşündüm ...

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

Aşağıdaki bağlantıya tıkladıktan sonra, bir blues riff oynamak için ana satır tuşlarını yazın (ayrıca aynı anda birden fazla tuş yazın vb.)

JThump kütüphanesini kullanarak örnek >> http://davealger.com/apps/jthump/

Temelde <iframe>, bir sesi oynayan bir sayfayı yükleyen görünmez öğeler oluşturarak çalışır .

Bu kesinlikle ideal değil, ancak bu çözümü tek başına yaratıcılığa dayalı olarak + 1'leyebilirsiniz (ve açık kaynak olduğu ve denediğim herhangi bir tarayıcıda çalıştığı gerçeği) Umarım bu en azından başka bir fikir arayan başka birine verir.

:)


Neden birisi bunu aşağı oyladı? Bana uygun bir seçenek gibi görünüyor.
Ocak'ta

oldukça hacky bir çözüm ama ben daha az çalışabilir bir örnek html 5 tuval oyunu yapmak için bu kütüphaneyi kullandık ... bu kütüphaneyi kullanarak oyun burada - beepbox.net
DaveAlger

0

Seçilen cevap IE dışında her şeyde çalışacaktır. Nasıl çapraz tarayıcı çalışması yapmak için bir öğretici yazdım = http://www.andy-howard.com/how-to-play-sounds-cross-browser-include-ie/index.html

İşte yazdığım fonksiyon;

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 sayfasına aşağıdaki etiketi de eklemeniz gerekir:

<bgsound id="sound">

Son olarak işlevi çağırabilir ve buradaki yoldan geçebilirsiniz:

playSomeSounds("sounds/welcome.wav");

0

Her zaman AudioContextsınırlı desteği olduğunu deneyebilirsiniz , ancak web ses api çalışma taslağının bir parçasıdır . Gelecekte bir şey yayınlamayı planlıyorsanız buna değebilir. Ve yalnızca krom ve Firefox için program yapıyorsanız altınsınız.


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

Web Audio API'si bu iş için doğru araçtır. Ses dosyalarını yüklemek ve çalmak için biraz iş var. Neyse ki, işi kolaylaştıran çok sayıda kütüphane var. Seslerle ilgilenmek için musquito adında bir kütüphane de oluşturdum. göz atabileceğiniz .

Şu anda sadece solma ses efektini destekliyor ve 3D uzamsallaştırma gibi diğer şeyler üzerinde çalışıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.