web-dev-qa-db-fra.com

Effets sonores en JavaScript / HTML5

J'utilise HTML5 pour programmer des jeux; l'obstacle que j'ai rencontré maintenant est de savoir comment jouer des effets sonores.

Les exigences spécifiques sont peu nombreuses:

  • Jouez et mixez plusieurs sons,
  • Jouez le même échantillon plusieurs fois, en superposant éventuellement des lectures,
  • Interrompre la lecture d’un échantillon à tout moment,
  • Lisez de préférence les fichiers WAV contenant du PCM brut (de faible qualité), mais je peux les convertir, bien sûr.

Ma première approche consistait à utiliser l'élément HTML5 <audio> et à définir tous les effets sonores de ma page. Firefox lit les fichiers WAV simplement, mais l'appel de #play plusieurs fois ne lit pas vraiment l'échantillon plusieurs fois. D'après ma compréhension de la spécification HTML5, l'élément <audio> suit également l'état de lecture, ce qui explique pourquoi.

Ma pensée immédiate était de cloner les éléments audio. J'ai donc créé la minuscule bibliothèque JavaScript suivante pour le faire pour moi (cela dépend de 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;
      };
    });
  }
};

Je peux donc maintenant utiliser Snd.boom(); à partir de la console Firebug et jouer snd/boom.wav, mais je ne peux toujours pas lire le même échantillon plusieurs fois. Il semble que l'élément <audio> soit davantage une fonctionnalité de diffusion en continu qu'un outil permettant de jouer des effets sonores.

Existe-t-il un moyen astucieux pour y parvenir qui me manque, en utilisant de préférence uniquement HTML5 et JavaScript?

Je dois également mentionner que mon environnement de test est Firefox 3.5 sur Ubuntu 9.10. Les autres navigateurs que j'ai essayés - Opera, Midori, Chromium, Epiphany - ont donné des résultats variables. Certains ne jouent rien, et certains jettent des exceptions.

313
Stéphan Kochen

HTML5 Audio objects

Vous n'avez pas besoin de vous embêter avec les éléments <audio>. HTML 5 vous permet d’accéder directement aux objets Audio :

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

Il n'y a pas de support pour le mixage dans la version actuelle de la spécification.

Pour reproduire le même son plusieurs fois, créez plusieurs instances de l'objet Audio. Vous pouvez également définir snd.currentTime=0 sur l'objet une fois la lecture terminée.


Comme le constructeur JS ne prend pas en charge les éléments de repli <source>, vous devez utiliser

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

pour vérifier si le navigateur prend en charge Ogg Vorbis.


Si vous écrivez un jeu ou une application musicale (plus qu'un lecteur), vous voudrez utiliser une API Web Audio plus avancée , qui est maintenant supporté par la plupart des navigateurs .

443
Kornel

WebAudio API par le W3C

À compter de juillet 2012, WebAudio API est désormais pris en charge dans Chrome, et au moins en partie dans Firefox, et doit être ajouté à IOS à partir de la version 6.

Bien qu'il soit suffisamment robuste pour être utilisé par programme pour des tâches de base, l'élément Audio n'a jamais été conçu pour fournir un support audio complet pour les jeux, etc. Il a été conçu pour permettre à un seul média d'être intégré dans une page, semblable à un étiquette. L'utilisation de la balise audio pour les jeux pose de nombreux problèmes:

  • Les bulletins de temps sont communs avec les éléments audio
  • Vous avez besoin d'un élément audio pour chaque instance d'un son
  • Les événements de charge ne sont pas encore totalement fiables
  • Pas de contrôles de volume communs, pas de fondu, pas de filtres/effets

J'ai utilisé cet article Premiers pas avec WebAudio pour commencer à utiliser l'API WebAudio. Le étude de cas FieldRunners WebAudio est également une bonne lecture.

36
Chris Jaynes

howler.js

Pour la création de jeux, l'une des meilleures solutions consiste à utiliser une bibliothèque qui résout les nombreux problèmes auxquels nous sommes confrontés lors de l'écriture de code pour le Web, tels que howler.js . howler.js résume le grand (mais de bas niveau) Web Audio API dans un framework facile à utiliser. Il tentera de revenir à élément audio HTML5 si l’API Web Audio n’est pas disponible.

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

Une autre excellente bibliothèque est wad.js , ce qui est particulièrement utile pour produire des sons synthétiques, tels que la musique et les effets. Par exemple:

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

Son pour les jeux

Une autre bibliothèque similaire à Wad.js est " Sound for Games ", elle est davantage axée sur la production d'effets, tout en fournissant un ensemble similaire de fonctionnalités via une API relativement distincte (et peut-être plus concise):

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

Sommaire

Chacune de ces bibliothèques mérite d'être examinée, que vous ayez besoin de lire un seul fichier son ou de créer votre propre éditeur de musique html, votre propre générateur d'effets ou votre jeu vidéo.

29
d13

Vous pouvez également l'utiliser pour détecter l'audio HTML 5 dans certains cas:

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

Fonction HTML 5 JS Detect

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

Voici une méthode pour rendre possible la lecture simultanée du même son. Combinez-le avec le préchargeur et vous êtes prêt. Cela fonctionne avec Firefox 17.0.1 au moins, je ne l’ai pas encore testé.

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

Liez-le à une touche du clavier et appréciez:

player("step");
5
F-3000

On dirait que vous voulez des sons multicanaux. Supposons que vous ayez 4 canaux (comme sur de très vieux jeux 16 bits), je n'ai pas encore appris à utiliser la fonctionnalité audio HTML5, mais vous n'avez pas besoin de 4 éléments <audio>, et du cycle utilisé jouer le prochain effet sonore? Avez-vous essayé ça? Ce qui se produit? Si cela fonctionne: Pour jouer plus de sons simultanément, ajoutez simplement plus d'éléments <audio>.

Je l'ai déjà fait auparavant sans l'élément <audio> HTML5, en utilisant un petit objet Flash de http://flash-mp3-player.net/ - J'ai écrit un quiz musical ( http : //webdeavour.appspot.com/ ) et l'a utilisé pour lire des extraits de musique lorsque l'utilisateur a cliqué sur le bouton de la question. Au départ, j'avais un joueur par question, et il était possible de les lire superposées. Je l'ai donc modifiée pour qu'il n'y ait qu'un seul joueur, que j'ai pointé vers différents clips musicaux.

4
Lee Kowalkowski

Regardez le i have (-> miroir ) (interface audio javascript) site. En regardant leur source, ils semblent appeler play() à plusieurs reprises, et ils mentionnent que leur bibliothèque pourrait être appropriée pour une utilisation dans des jeux basés sur HTML5.

Vous pouvez déclencher plusieurs événements audio simultanément, ce qui peut être utilisé pour créer des jeux Javascript ou avoir une voix parlant sur une musique de fond.

4
Raul Agrait

Voici une idée. Chargez tout votre audio pour une certaine classe de sons dans un seul élément audio où les données src sont tous vos échantillons dans un fichier audio contigu (vous voulez probablement un peu de silence entre vous pour pouvoir attraper et couper les échantillons avec un délai d'expiration avec moins risque de saignement au prochain échantillon). Ensuite, recherchez l’échantillon et jouez-le au besoin.

Si vous avez besoin de plus d'un de ceux-ci pour jouer, vous pouvez créer un élément audio supplémentaire avec le même src afin qu'il soit mis en cache. Maintenant, vous avez effectivement plusieurs "pistes". Vous pouvez utiliser des groupes de pistes avec votre schéma d’allocation de ressources préféré tel que Round Robin, etc.

Vous pouvez également spécifier d'autres options, telles que la mise en file d'attente de sons dans une piste à reproduire lorsque cette ressource devient disponible ou la découpe d'un échantillon en cours de lecture.

3
digitalicarus

Pour lire le même échantillon plusieurs fois, ne serait-il pas possible de faire quelque chose comme ceci:

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

(e est l'élément audio)

J'ai peut-être complètement mal compris votre problème. Voulez-vous que l'effet sonore se répète plusieurs fois en même temps? Alors c'est complètement faux.

3
adamse

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

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

Fonctionne correctement dans Firefox et Chrome pour moi.

Pour arrêter un son que vous avez démarré, faites var sound = document.getElementById ("shot"). CloneNode (true); sound.play (); et plus tard sound.pause ();

2
Robert O'Callahan

Je recommanderais d'utiliser SoundJS , une bibliothèque que j'ai aidé à développer. Il vous permet d'écrire une base de code unique qui fonctionne partout, avec SoundJS sélectionnant l'audio Web, l'audio HTML ou l'audio flash, selon le cas.

Cela vous permettra de faire tout ce que vous voulez:

  • Jouez et mixez plusieurs sons,
  • Jouez le même échantillon plusieurs fois, en superposant éventuellement des lectures
  • Interrompre la lecture d'un échantillon à tout moment
  • lire des fichiers WAV contenant (en fonction de la prise en charge du navigateur)

J'espère que ça t'as aidé.

2
OJay

Il n'est pas possible de jouer à plusieurs coups avec un seul élément <audio>. Vous devez utiliser plusieurs éléments pour cela.

1
Eli Grey

Je me suis heurté à cela lors de la programmation d'un générateur de cartes Musicbox. Commencé avec différentes bibliothèques, mais à chaque fois, il y avait un problème. Le retard sur l'implémentation audio normale était mauvais, pas de lectures multiples ... finirent par utiliser la bibliothèque lowlag + soundmanager:

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

Vous pouvez vérifier l'implémentation ici: http://musicbox.grit.it/

J'ai généré des fichiers wav + ogg pour des lectures sur plusieurs navigateurs. Ce lecteur de musicbox fonctionne sur ipad, iphone, Nexus, mac, pc, ... fonctionne pour moi.

1
Grit

La réponse sélectionnée fonctionnera dans tout sauf IE. J'ai écrit un tutoriel sur la façon de le faire fonctionner cross browser = http://www.andy-howard.com/how-to-play-sounds-cross-browser-including-ie/index.html =

Voici la fonction que j'ai écrite;

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

Vous devez également ajouter la balise suivante à la page html:

<bgsound id="sound">

Enfin, vous pouvez appeler la fonction et simplement passer par le chemin ici:

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

Je sais que c'est un piratage total mais j'ai pensé ajouter cet exemple de bibliothèque audio open source que j'ai mise sur github il y a quelque temps ...

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

Après avoir cliqué sur le lien ci-dessous, tapez sur les touches de la ligne de départ pour jouer un riff blues (tapez également plusieurs touches en même temps, etc.).

Echantillon utilisant la bibliothèque jThump >> http://davealger.com/apps/jthump/

Cela fonctionne essentiellement en créant des éléments <iframe> invisibles qui chargent une page qui lit un son onReady ().

Ce n'est certainement pas l'idéal mais vous pouvez +1 utiliser cette solution basée uniquement sur la créativité (et le fait qu'elle soit open source et qu'elle fonctionne dans n'importe quel navigateur J'ai essayé) J'espère que cela donnera à quelqu'un d'autre des idées au moins.

:)

0
DaveAlger

Vous pouvez toujours essayer AudioContext le support est limité, mais cela fait partie du brouillon web audio api . Cela pourrait valoir la peine si vous envisagez de publier quelque chose dans le futur. Et si vous ne programmez que pour chrome et Firefox, vous êtes en or.

0
haelmic
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
user1024

L'API Web Audio est l'outil idéal pour ce travail. Il y a un peu de travail impliqué dans le chargement et la lecture de fichiers de sons. Heureusement, il existe de nombreuses bibliothèques qui simplifient le travail. Étant intéressé par les sons, j'ai également créé une bibliothèque appelée musquito , vous pouvez également y accéder.

Actuellement, il ne prend en charge que les effets sonores atténués et je travaille sur d'autres éléments tels que la spatialisation 3D.

0
VJAI