html - Ljud effekter i JavaScript/HTML5
Jag använder HTML5 för att programmera spel; hindret jag har stött på nu är hur man spelar upp ljudeffekter.
De specifika kraven är få till antalet:
- Spela och blanda flera ljud,
- Spela samma prov flera gånger, eventuellt med överlappande uppspelningar,
- Avbryt uppspelning av ett prov när som helst,
- Föredrar att spela WAV-filer som innehåller (lågt kvalitets-) rå PCM, men jag kan naturligtvis konvertera dessa.
Mitt första tillvägagångssätt var att använda HTML5 <audio>-elementet och definiera alla ljudeffekter på min sida. Firefox spelar WAV-filerna helt utmärkt, men att kalla #play flera gånger spelar egentligen inte upp exemplet flera gånger. Utifrån min förståelse av HTML5-specifikationen spårar <audio>-elementet också uppspelningsstatus, vilket förklarar varför.
Min omedelbara tanke var att klona ljud elementen, så jag skapade följande lilla JavaScript-bibliotek för att göra det åt mig (beroende av 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;
};
});
}
};
Så nu kan jag göra Snd.boom(); från Firebug-konsolen och spela snd/boom.wav, men jag kan fortfarande inte spela samma ljudprov flera gånger. Det verkar som att <audio>-elementet verkligen är mer en strömningsfunktion än något att spela ljudeffekter med.
Finns det ett smart sätt att få detta att hända som jag missar, helst bara med HTML5 och JavaScript?
Jag bör också nämna att min testmiljö är Firefox 3.5 på Ubuntu 9.10. De andra webbläsare jag har provat - Opera, Midori, Chromium, Epiphany - gav varierande resultat. Vissa spelar inte upp något alls, och vissa kastar undantag.
Svar #1
HTML5 Audio-objekt
Du behöver inte bry dig om <audio>-element. HTML 5 låter dig komma åt Audio-objekt direkt:
var snd = new Audio("file.wav"); // buffers automatically when created
snd.play();
Det finns inget stöd för blandning i den nuvarande versionen av specifikationen.
För att spela samma ljud flera gånger, skapa flera instanser av Audio-objektet. Du kan också sätta snd.currentTime=0 på objektet efter att det har spelats klart.
Eftersom JS-konstruktorn inte stöder fallback <source>-element, bör du använda
(new Audio()).canPlayType("audio/ogg; codecs=vorbis")
för att testa om webbläsaren stöder Ogg Vorbis.
Om du skriver ett spel eller en musikapp (mer än bara en spelare), kommer du att vilja använda mer avancerad Web Audio API, som nu stöds av de flesta webbläsare.
Svar #2
Webb-ljud-API
Redigera: Från och med december 2021 stöds Web Audio API i princip i Chrome, Firefox, Safari och alla andra större webbläsare (exklusive IE, förstås).
Från och med juli 2012 stöds Web Audio API nu i Chrome, och är åtminstone delvis stödd i Firefox, och planeras att läggas till i IOS från version 6.
Även om Audio-elementet är tillräckligt robust för att användas programmatiskt för grundläggande uppgifter, var det aldrig avsett att ge fullständigt ljudstöd för spel och andra komplexa applikationer. Det var designat för att tillåta att en enda mediefil bäddas in på en sida, liknande en img-tagg. Det finns många problem med att försöka använda det för spel:
- Tidsavvikelser är vanliga med
Audio-element - Du behöver ett
Audio-element för varje instans av ett ljud - Laddningshändelser är inte helt pålitliga än
- Inga vanliga volymkontroller, ingen toning, inga filter/effekter
Här är några bra resurser för att komma igång med Web Audio API:
- MDN-dokumentation
- Komma igång med WebAudio-artikeln
- FieldRunners WebAudio fallstudie är också en bra läsning
Svar #3
howler.js
För spelutveckling är en av de bästa lösningarna att använda ett bibliotek som löser de många problem vi möter när vi skriver kod för webben, såsom howler.js. howler.js abstrakterar det stora (men låg nivå) Web Audio API till ett lättanvänt ramverk. Det kommer att försöka falla tillbaka på HTML5 Audio Element om Web Audio API inte är tillgängligt.
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
Ett annat bra bibliotek är wad.js, vilket är särskilt användbart för att skapa synthljud, såsom musik och effekter. Till exempel:
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}
})
Ljud för spel
Ett annat bibliotek liknande Wad.js är "Sound for Games", det har mer fokus på produktion av effekter, samtidigt som det erbjuder en liknande uppsättning funktionalitet genom ett relativt distinkt (och kanske mer koncist kännande) 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?]
);
}
Sammanfattning
Var och en av dessa bibliotek är värda en titt, oavsett om du behöver spela upp en enda ljudfil, eller kanske skapa din egen HTML-baserade musikredigerare, effektskapare eller videospel.
