Game development: restart the sound(<audio> element) before it ended playing - javascript

I ran into some issues regarding my small-web-game project:
I have some sound files, given in HTML like this:
<audio id="shotSound" preload="auto">
<source src="../sound/shot.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio>
the preload="auto" should load the content immediately on page init right?
Now I'm using javascript to trigger the sound when I need to (key press):
var audio = document.getElementById("shotSound");
audio.play();
This works, but if I try to shot continuously or just faster(one shot after another) it won't work for shots after the first one. So, what happens if I hold the "shot" button: the sound is heard like it would be on repeat - which is obviously wrong.
Any ideas/suggestions are very welcome!
If I was unclear, please do let me know.
Thank you

Don't put the audio-tag into the HTML document. Preload the sound-effect in Javascript using
shotSound = new Audio();
shotSound.src = "../sound/shot.mp3";
shotSound.load();
Keep the shotSound variable in scope, so it doesn't get garbage-collected. Then, when you need to play a sound, create a new Audio object:
new Audio("../sound/shot.mp3").play();
It will play immediately because the sound-file will already be cached. And because it's a new audio-object, it won't interrupt other instances of the same effect playing in parallel.

Related

Plyr audio player muted for the first second of audio

I am using Plyr audio player for my Rails app, along with Simulus.js.
I dynamically add audio source when the user clicks on different audio buttons. Then I launch the audio player with the .play() method.
However, the beginning of the track can't be heard. You can try it out on this URL, by taping the first audio player. If you put back the audio cursor to the beginning, then you can hear the very beginning of the track.
Here is my HTML:
<audio class="player" controls data-dicteeModule-target="player">
<source class="player-source" src="<%= dictee_modules.first.audio_url %>" type="audio/mp3" />
</audio>
Here is how I initialize the player:
initialize() {
const players = document.getElementsByClassName('player');
var player = [];
Array.from(players).forEach(function (ele, i) {
player[i] = new Plyr(ele, {
controls: ['progress']
});
});
}
Here is my Stimulus onclick action:
var player = this.playerTarget;
var source = audio.getAttribute("data-audio-source");
var audioSource = player.getElementsByClassName("player-source")[0];
audioSource.src = source;
player.load();
player.addEventListener('canplay', (event) => {
player.play();
});
Any idea why the very beginning of the track is not heard?
Thanks.
This happens to me too on various websites that need to use audio after no audio was used for a while, even on YouTube. I'm using Chrome 104.0.5112.81 on Windows 10.
It's likely a driver issue you can't do much about (assuming YouTube would fix it if they could). It looks like Windows or Chrome ends up dimming the sound way too quickly, and takes too long turning it back on.
Unfortunately I couldn't find anything on Google yet. It seems hard to make Google understand this query, it only returned results about audio preventing PC sleep mode (or other unrelated common issues), no matter how I phrased it. Could also indicate it's just a very obscure issue with one or a few particular drivers.

audio onended not firing in Ionic

I am currently making a simple music app with the Ionic framework as practice. This is my first time working with Ionic and first time working with AngularJS. Right now i want to make sure that when a song from a certain playlist is finished, the next one starts. However, the onended HTMLproperty doesn't seem to do anything.
First Try
menu.html
<audio ng-src="{{ audioSrc }}" controls class="player" id="trackPlayer" autoplay="true" onended="nextTrack()">
<source type="audio/mpeg">
Your browser does not support the audio element.
</audio>
controller.js
//check if audio is finished
$scope.nextTrack = function () {
//find the right playlist and right current song id
alert("ended");
console.log($rootScope.nowPlaying);
//set new audiosrc for audioplayer
}
I'm also trying to target the audioplayer directly by javascript, but this doesn't work either.
Second try
controller.js
document.getElementById('trackPlayer').addEventListener('onended', $scope.nextTrack());
Putting an alert('ended!') in onended in my audio tag works but anything else does not give a response when my audio is done playing.
I have looked all over but did not find a solution or an explenation yet.
Anybody knows what I am doing wrong?
Thanks in advance.

Audio stops playing while moving to fallback mount using Icecast

I was wondering if someone has had a similar problem:
I have defined fallback mounts in Icecast2 so that one major stream plays at all times. If another fallback mount becomes active, the latter becomes the active.
I have tested the streams (mp3 format), with ffplay and the transition happens with no problem. The problem exists when I use an html5 audio tag to listen to the audio: transition does not happen automatically and I have to reload the browser and click play in order to listen to the stream. That is, using the browser, when the fallback stream gets enabled, the sound stops and I have to reload the browser and click play in order to listen[to the other stream]. The same problems occurs in all major browsers.
Here's an excerpt from my icecast.xml:
<mount>
<public>0</public>
<mount-name>/stream</mount-name>
<hidden>0</hidden>
</mount>
<mount>
<public>0</public>
<mount-name>/stream1</mount-name>
<fallback-mount>/stream</fallback-mount>
<fallback-override>1</fallback-override>
<username>stream1</username>
<password>pass</password>
<hidden>0</hidden>
</mount>
This is what ffplay shows while connecting and disconnecting from the secondary source:
The html5 code that plays the audio is as follows:
<audio controls>
<source src="http://127.0.0.1:3333/stream1" type="audio/mpeg">
</audio>
I got this finally working by going as follows:
First I noticed that when I switched from one mount point to another by enabling the source, the audio stopped playing. I set up a timer to fire every 1 second in order to check audio.currentTime and compare to an previous value. Then when the result is true, I reset the audio source to the same stream. It's kind of a hack but it seems to solve the trick.
html code:
<audio id="audio" controls>
<source src="http://127.0.0.1:3333/stream1" type="audio/mp3">
</audio>
javascript code:
var audio = document.getElementById('audio');
var myVar = setInterval(myTimer, 1000);
var oldTime = "";
function myTimer() {
if ((audio.paused != true && (audio.currentTime - oldTime) == 0 )) {
audio.src="";
audio.src="http://127.0.0.1:3333/stream1";
audio.play();
}
oldTime = audio.currentTime;
};

Playing multiple looping sounds on a website

Is there a 'best way' to play sounds/music on a website? Should I use JS plugin? SWF app or a HTML element? Also I want it to support volume that can be controlled via HTML slider.
If I want to play multiple sounds/music on top of each other do I have to have a 'player' for each one of them or can I have one player playing multiple sounds?
Last time I needed to add sounds to my website was like 10 years ago so I have no idea what techniques people use nowadays.
It's actually very simple. HTML5 makes it easy by introducing the <audio> tag.
This uses the default audio controls:
<audio loop controls><source src="yoursoundhere.mp3" type="audio/mpeg"></audio>
The loop attribute makes it auto-loop. Add the autoplay attribute if you want it to start playing on load. Multiple audio tags play over each other.
Note that this only works with MP3. Otherwise, you need to change the type of file.
If you want a custom slider, here is something you could try:
<audio loop id="audio"><source src="yoursoundhere.mp3" type="audio/mpeg"></audio>
<script>
//When slider value updates.
function updateSlider(){
var audioplayer = document.getElementByID("audio");
var controlvalue = yourHTMLsliderValue();
audioplayer.volume = controlvalue;
}
//First Time.
var audioplayer = document.getElementByID("audio");
var controlvalue = yourHTMLsliderValue();
audioplayer.volume = controlvalue;
</script>
Also note that the supported audio filetypes are .mp3, .ogg, and .wav, and that this only works in HTML5.

Playing random audio in HTML/Javascript

I am trying to figure out how to continuously play random audio sound bites, one after another without having them overlap on an HTML page using jquery. I have code that plays random sound bites on a timer, but sometimes they overlap and sometimes there is a pause in between the sounds. I had looked into ended and other EventListeners but I really have no idea what I am doing. Here is a portion my code:
<html>
<audio id="audio1">
<source src="cnn.mp3"></source>
</audio>
<audio id="audio2">
<source src="sonycrackle.mp3"></source>
</audio>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('audio').each(function(){
this.volume = 0.6;
});
var tid = setInterval(playIt, 2000);
});
function playIt() {
var n = Math.ceil(Math.random() * 2);
$("#audio"+n).trigger('play');
};
Is there a way to just continuously play these sounds bites one after another right after the previous sound plays? FWIW I have many sound bites but I am just showing two above for reference.
So I dabbled a bit, here's a full pure JavaScript solution.
Should be cross-browser, haven't tested (/lazy). Do tell me if you find bugs though
var collection=[];// final collection of sounds to play
var loadedIndex=0;// horrible way of forcing a load of audio sounds
// remap audios to a buffered collection
function init(audios) {
for(var i=0;i<audios.length;i++) {
var audio = new Audio(audios[i]);
collection.push(audio);
buffer(audio);
}
}
// did I mention it's a horrible way to buffer?
function buffer(audio) {
if(audio.readyState==4)return loaded();
setTimeout(function(){buffer(audio)},100);
}
// check if we're leady to dj this
function loaded() {
loadedIndex++;
if(collection.length==loadedIndex)playLooped();
}
// play and loop after finished
function playLooped() {
var audio=Math.floor(Math.random() * (collection.length));
audio=collection[audio];
audio.play();
setTimeout(playLooped,audio.duration*1000);
}
// the songs to be played!
init([
'http://static1.grsites.com/archive/sounds/background/background005.mp3',
'http://static1.grsites.com/archive/sounds/background/background006.mp3',
'http://static1.grsites.com/archive/sounds/background/background007.mp3'
]);
Some quick suggestions is add the attribute preload="auto" to the audio element and change the script to be $(window).onload instead of document ready. Document ready fires when html is in place but not necessarily when audio and other assets (like images) have loaded.
You could also look into using the AudioBuffer Interface in the new Web Audio API, it's described as "this interface represents a memory-resident audio asset (for one-shot sounds and other short audio clips)." which sounds like what you need. I believe part of the issues you're having (random pauses/delays/sound glitches with the audio element) are one of the reasons why it's being developed.
Read more here:
https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AudioBuffer
Unfortunately it's only Chrome and lastest Safari supported with Firefox support supposedly in the next 6(ish) months and no word yet on IE support.

Categories

Resources