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:

  • Jouer et mélanger plusieurs sons,
  • jouer le même échantillon plusieurs fois, éventuellement des lectures qui se chevauchent,
  • Interrompre la lecture d'un échantillon à tout moment,
  • de préférence jouer des fichiers WAV contenant (faible qualité) PCM brut, mais je peux les convertir, bien sûr.

Ma première approche était de utilisez L'élément HTML5 <audio> et définissez tous les effets sonores dans ma page. Firefox joue les fichiers WAV juste peachy, mais appeler #play plusieurs fois ne joue 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 petite bibliothèque JavaScript suivante pour le faire pour moi (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;
      };
    });
  }
};

Alors maintenant je peux faire Snd.boom(); de la console Firebug et play snd/boom.wav, mais je ne peux toujours pas jouer le même échantillon plusieurs fois. Il semble que l'élément <audio> est vraiment plus une fonctionnalité de streaming que quelque chose avec lequel jouer des effets sonores.

Existe-t-il un moyen intelligent de faire en sorte que cela me manque, de préférence en utilisant uniquement HTML5 et JavaScript?

Je devrais é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 - produits des résultats variables. Certains ne jouent rien, et certains jettent des exceptions.

304
demandé sur vaxquis 2009-12-19 22:57:00

16 réponses

HTML5 Audio objets

Vous n'avez pas besoin de vous soucier des éléments <audio>. HTML 5 vous permet d'accéder à Audio objets directement:

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

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

Pour lire 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 après la fin de la lecture.


Puisque le constructeur JS ne prend pas en charge les éléments fallback <source>, vous devez utiliser

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

Pour tester si le navigateur prend en charge Ogg Vorbis.


Si vous écrivez un jeu ou une application musicale (plus qu'un simple lecteur), vous aurez envie d'utiliser API Audio Web plus avancé , qui est maintenant pris en charge par la plupart des navigateurs.

435
répondu Kornel 2017-06-30 07:30:39

WEBAUDIO API par W3C

À partir de juillet 2012, l'API WebAudio est maintenant pris en charge dans Chrome, et au moins en partie pris en charge dans Firefox, et devrait être ajouté à IOS à partir de la version 6.

Bien qu'il soit assez robuste pour être utilisé par programmation pour les 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, similaire à une balise img. Il y a beaucoup de problèmes liés à l'utilisation de la balise Audio pour les jeux:

  • les bordereaux de synchronisation 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 chargement ne sont pas totalement fiables, pour le moment
  • Pas de contrôle de volume commun, Pas de décoloration, pas de filtres/effets

J'ai utilisé cet article mise en route avec WebAudio pour commencer avec L'API WebAudio. L'étude de cas Webaudio FieldRunners est également une bonne lecture.

34
répondu Chris Jaynes 2017-06-30 07:27:43

Hurleur.js

Pour la création de jeux, l'une des meilleures solutions est d'utiliser une bibliothèque qui résout les nombreux problèmes que nous rencontrons lors de l'écriture de code pour le web, tels que howler.js . hurleur.js résume la grande (mais de bas niveau) Web Audio API dans un cadre facile à utiliser. Il tentera de revenir à élément Audio HTML5 si L'API Audio Web 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 grande bibliothèque est wad.js , qui est particulièrement utile pour produire de l'audio de synthé, comme 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}
})

Le Son pour les Jeux

Une autre bibliothèque similaire à Wad.js est "Son pour les jeux ", il se concentre davantage sur la production d'effets, tout en fournissant un ensemble similaire de fonctionnalités grâce à 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?]
  );
}

Résumé

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

25
répondu d13 2016-06-02 03:16:33

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

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

HTML 5 js détecter Fonction

function supportsAudio()
{
    var a = document.createElement('audio'); 
    return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
}
9
répondu Rob 2011-10-05 20:28:32

Voici une méthode pour permettre de jouer même le même son simultanément. Combiner avec preloader, et vous êtes tous ensemble. Cela fonctionne avec Firefox 17.0.1 au moins, ne l'ont pas encore testé avec autre chose.

// 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 ceci à une touche du clavier, et profitez:

player("step");
5
répondu F-3000 2012-12-24 14:04:31

On dirait que ce que vous voulez, c'est des sons multicanaux. Supposons que vous ayez 4 canaux (comme sur de très vieux jeux 16 bits), Je n'ai pas encore joué avec la fonctionnalité audio HTML5, mais n'avez-vous pas juste besoin de 4 éléments

Je l'ai déjà fait sans l'élément HTML5

4
répondu Lee Kowalkowski 2010-02-18 21:43:14

Jetez un oeil à la jai (-> miroir) (Bienvenue sur le 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 les jeux basés sur HTML5.

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

4
répondu Raul Agrait 2018-03-22 15:26:41

Pour jouer 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)

Peut-être que j'ai complètement mal compris votre problème, Voulez-vous que l'effet sonore joue plusieurs fois en même temps? Ensuite, ce qui est totalement faux.

3
répondu adamse 2009-12-19 20:19:58

Voici une idée. Chargez tout votre audio pour une certaine classe de sons dans un seul élément audio individuel où les données src sont tous vos échantillons dans un fichier audio contigu (vous voulez probablement un peu de silence entre vous afin que vous puissiez attraper et couper les échantillons avec un délai d'attente avec moins de risque de saignement à l'échantillon suivant). Ensuite, cherchez l'échantillon et jouez-le en cas de 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 est mis en cache. Maintenant, vous avez effectivement plusieurs "pistes". Vous pouvez utiliser des groupes de pistes avec votre système d'allocation de ressources préféré comme Round Robin, etc.

Vous pouvez également spécifier d'autres options comme mettre en file d'attente des sons dans une piste à lire lorsque cette ressource devient disponible ou couper un échantillon en cours de lecture.

3
répondu digitalicarus 2012-08-30 13:48:17

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

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

Fonctionne bien dans Firefox et Chrome pour moi.

Pour arrêter un son que vous avez commencé, faites var sound = document.getElementById("coup de feu").cloneNode (vrai); son.jouer(); et plus tard son.pause ();

2
répondu Robert O'Callahan 2012-01-11 23:58:17

Je recommande 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:

  • Jouer et mélanger plusieurs sons,
  • jouer le même échantillon plusieurs fois, éventuellement des lectures qui se chevauchent
  • Interrompre la lecture d'un échantillon à tout moment
  • lire les fichiers WAV contenant (selon le support du navigateur)

J'espère que ça aide.

2
répondu OJay 2013-10-03 18:21:14

Il n'est pas possible de faire un jeu multi-shot avec un seul élément <audio>. Vous devez utiliser plusieurs éléments pour cela.

1
répondu Eli Grey 2009-12-19 23:04:48

J'ai rencontré cela en programmant un générateur de cartes musicbox. Commencé avec différentes bibliothèques, mais chaque fois qu'il y avait un problème en quelque sorte. Le retard sur la mise en œuvre audio normale était mauvais, pas de jeux multiples... finalement fini par utiliser lowlag library + soundmanager:

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

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

J'ai généré fichiers WAV + ogg pour les jeux multi navigateur. Ce lecteur musicbox fonctionne réactif sur ipad, iphone, Nexus, mac, pc,... fonctionne pour moi.

1
répondu Grit 2014-04-01 06:24:47

Je sais que c'est un hack total, mais j'ai pensé que je devrais ajouter cet exemple de bibliothèque audio open source que j'ai mis 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 d'accueil pour jouer un riff de blues (Tapez également plusieurs touches en même temps, etc.)

Exemple d'utilisation de la bibliothèque jThump > > http://davealger.com/apps/jthump/

Cela fonctionne essentiellement en rendant invisibles <iframe> les éléments qui chargent une page qui joue un son onReady ().

Ce n'est certainement pas idéal mais vous pourriez +1 Cette solution basée sur la créativité seule (et le fait qu'elle soit open source et fonctionne dans n'importe quel navigateur que je l'ai essayé) j'espère que cela donne à quelqu'un d'autre la recherche d'idées au moins.

:)

0
répondu DaveAlger 2014-01-27 22:29:16

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 de la page html:

<bgsound id="sound">

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

playSomeSounds("sounds/welcome.wav");
0
répondu Andrew Junior Howard 2014-08-12 12:05:02

Vous pouvez toujours essayer AudioContext il a un support limité, mais il fait partie du projet de travail Web Audio api. Cela pourrait en valoir la peine si vous prévoyez de libérer quelque chose à l'avenir. Et si vous ne programmez que pour chrome et Firefox, vous êtes en or.

0
répondu haelmic 2016-08-29 03:23:52