astralaaron Posted November 7, 2013 Share Posted November 7, 2013 (edited) I need to be able to preload my audio files for some small games I am making... Ideally I would like to do it similarly to how I am preloading my images, as shown in the following code: this.preload = function(images) { var loaded = 0; for (var i = 0; i < images.length; i++) { var temp = new Image(); temp.addEventListener("load", function() { loaded++; if (loaded == images.length) LOADED = true; }, true); temp.src = images[i]; } } I am having a hard time searching around the web for help.. still looking, just thought I would start a thread to see if anyone here has an answer, or knows a good site with info. edit: I am aware of this: HTML5 preload attribute However I need to be able to detect when all audio is loaded before executing certain code... Edited November 7, 2013 by astralaaron Link to comment Share on other sites More sharing options...
Ingolme Posted November 7, 2013 Share Posted November 7, 2013 You can check for the canplaythrough event. Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 (edited) Perfect, thank you. I am pretty close to having this working...I have one problem though. Since I am creating my audio elements with javascript, how do I go about adding multiple sources (one for mp3 and 1 for ogg) ? for example: <audio controls> <source src="horse.ogg" type="audio/ogg"> <source src="horse.mp3" type="audio/mpeg"></audio> Edit, just found this page which seems like it will work: http://stackoverflow.com/questions/4053262/how-can-i-add-multiple-sources-to-an-html5-audio-tag-programmatically Edited November 8, 2013 by astralaaron Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 (edited) I have ran into a problem...my sound preloading seems to work fine in FireFox, but will not work with IE. this.loadSounds = function(snd) { var loadedSounds = 0; for (var i = 0; i < snd.length; i++) { var temp = new Audio(); temp.addEventListener("canplaythrough", function() { loadedSounds++; console.log('SOUND LOADED ' + loadedSounds); if (loadedSounds == snd.length){ LOADED_SND = true; console.log('LOADED_SND ' + LOADED_SND); } }, true); if (temp.canPlayType('audio/mpeg')) { console.log('temp canPlayType mp3'); temp.type = "audio/mpeg"; temp.src = snd[i] + ".mp3"; } else { temp.type = "audio/ogg"; console.log('temp canPlayType ogg'); temp.src = snd[i] + ".ogg"; } //temp.preload = "auto"; console.log('after canplaythrough event set'); } } these console.log()'s fire in IE: console.log('temp canPlayType mp3'); console.log('after canplaythrough event set'); however, the addEventListener function never happens, does anyone know why? and a fix? thank you. EDIT: is temp.preload = "auto"; neccessary? Edited November 8, 2013 by astralaaron Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 Well, this doesn't seem to be a good method anyway, as Chrome seems to not preload the audio. I read on a website saying that chrome fires the canplaythrough event imediately after the canplay event. (therefore is basically useless, as they put it) is there any other way to detect the file has loaded? also..the addEventListener seems to not be working at all on IE. I've tried the 'progress' event as well, which works on firefox and, still nothing on IE... Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 ok, I figured out in IE you must appendChild(temp) before adding an event listener in order for it to work... That only solves one problem, in Chrome, the preload doesn't work considering 'canplaythrough' fires immediately after 'canplay'. Any suggestions are very appreciated Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 OMG.... I cannot catch a break with Chrome. I am trying this: temp.addEventListener("progress", function() { tracker++; console.log(tracker + " progress= " + this.buffered.end(0) + ' total duration = ' + this.duration); //if(this.buffered.end(0) >= this.duration) }, true); which looked very promising on firefox and IE with the final output of the console looking like I can simply check this.buffered.end(0) against this.duration... FireFox console output: 2 progress fireing : 317.966333 total duration : 317.966333 Internet Explorer output: 17 progress fireing : 317.9716666 total duration : 317.9716666 And then Chrome has to go and output this: 6 progress= 93.07910919189453 total duration = 317.936327 I don't know what to do with chrome..... Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 even stranger now, I tried with a different sound file and chrome outputs this: 93.59673309326172 total duration = 93.596735 why with the other sound file does it out put this: ?? progress= 93.20076751708984 total duration = 317.936327 Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 Well, it looks like AJAX is the best way to go about it so it works cross browser...I got it working anyway. I would like to hear if anyone has a solution for what I was trying to do above. Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 I am pretty sure it is preloading... does it even make sense? just call the sound file with an ajax call? viewing the developer network tool it shows it downloading the information from the sound file. but when that is done, does that mean the sound file is cached, or "preloaded" ? Link to comment Share on other sites More sharing options...
justsomeguy Posted November 8, 2013 Share Posted November 8, 2013 You should be able to tell in the network console. When you later play the sound, if you see another request for the mp3 with a 200 response then it was downloaded again. If it shows a 304 response then the server is telling the browser to use the cached version. If you don't see any request at all then the browser doesn't bother to ask the server, it just plays what it already downloaded. Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 Thanks JSG Link to comment Share on other sites More sharing options...
astralaaron Posted November 8, 2013 Author Share Posted November 8, 2013 (edited) ahh well again chrome is showing a different result form other browsers.... It downloads from the AJAX call, then once the sound begins, it posts a 204 "partial content" status and begins downloading again as the music plays.. EDIT: [ I guess there is no way to force chrome to check for a cached file? ] Something that might solve my problem would be if I could just detect when addEventListener("progress", STOPS fireing.. is there any way I could do that? Although a problem with it might be if the file is already buffered..I think it might not even fire the progress event.. Does anyone know if it is possible anyway? Edited November 9, 2013 by astralaaron Link to comment Share on other sites More sharing options...
astralaaron Posted November 9, 2013 Author Share Posted November 9, 2013 I meant "206 partial content" Link to comment Share on other sites More sharing options...
astralaaron Posted November 9, 2013 Author Share Posted November 9, 2013 ahhh appears as if the ajax preloading is not working at all.. status 200 again once the sound starts playing in IE and 206 status in chrome and firefox Link to comment Share on other sites More sharing options...
astralaaron Posted November 9, 2013 Author Share Posted November 9, 2013 I guess I will have to settle with "canplaythrough" even though chrome fires it immediately... Link to comment Share on other sites More sharing options...
Ingolme Posted November 9, 2013 Share Posted November 9, 2013 I'm quite sure Chrome will work just fine. The <audio> and <video> elements, the way browsers have implented then, don't necessarily have to load fully.Some browsers may choose to load only part of a file and load the rest after the file has started playing. This is up to the browser's implementation. It's possible that Chrome only fires the "canplay" event when "canplaythrough" is ready, which means that you really don't have any problem at all. Link to comment Share on other sites More sharing options...
astralaaron Posted November 9, 2013 Author Share Posted November 9, 2013 I'm quite sure Chrome will work just fine. The <audio> and <video> elements, the way browsers have implented then, don't necessarily have to load fully.Some browsers may choose to load only part of a file and load the rest after the file has started playing. This is up to the browser's implementation. It's possible that Chrome only fires the "canplay" event when "canplaythrough" is ready, which means that you really don't have any problem at all. I am going back to this method...but I am having an issue with Chrome (again....) here is the code I am using for the preload: this.loadSounds = function( path, snd ) { if (snd.length < 1) LOADED_SND = true; var loadedSounds = 0; for (var i = 0; i < snd.length; i++) { var temp = new Audio(); document.body.appendChild(temp); temp.addEventListener("canplaythrough", function() { loadedSounds++; console.log('SOUND LOADED ' + loadedSounds); if (loadedSounds == snd.length){ LOADED_SND = true; console.log('LOADED_SND ' + LOADED_SND); } }, true); if (temp.canPlayType('audio/ogg')) { temp.type = "audio/ogg"; console.log('temp canPlayType ogg'); temp.src = path + snd[i] + ".ogg"; } else { console.log('temp canPlayType mp3'); temp.type = "audio/mpeg"; temp.src = path + snd[i] + ".mp3"; } //temp.preload = "auto"; console.log('after canplaythrough event set'); } } The issue now is that after all of the sounds preload, Chrome will not play the sound when I create another instance of it. For example, this loading happens before each stage runs its "init()" function. The sounds get loaded, then the init() gets run. within the init function there is something like this: this.bgMusic = new Audio(); //this line is actually called when the object of the class is created, not in the init()if (this.bgMusic.canPlayType('audio/ogg')) { this.bgMusic.type = "audio/ogg"; this.bgMusic.src = "audio/Clasico.ogg"; } else { this.bgMusic.type = "audio/mpeg"; this.bgMusic.src = "audio/Clasico.mp3"; } this.bgMusic.play(); The problem which seems to be happening, is after the preload function, when trying to load / play that sound later in the game, it doesn't play. From watching the network tools, it appears that it will not call the same sound file twice. it says status "pending". now if I change it and add a random number to the end of the sound file name (similar to AJAX requests to the same file), then it will call the file and play the sound. for example: this.loadSounds = function( path, snd ) { if (snd.length < 1) LOADED_SND = true; var loadedSounds = 0; for (var i = 0; i < snd.length; i++) { var rand = Math.floor(Math.random() * 100) + 1; var temp = new Audio(); document.body.appendChild(temp); temp.addEventListener("canplaythrough", function() { loadedSounds++; console.log('SOUND LOADED ' + loadedSounds); if (loadedSounds == snd.length){ LOADED_SND = true; console.log('LOADED_SND ' + LOADED_SND); } }, true); if (temp.canPlayType('audio/ogg')) { temp.type = "audio/ogg"; console.log('temp canPlayType ogg'); temp.src = path + snd[i] + ".ogg" + "?r=" + rand; } else { console.log('temp canPlayType mp3'); temp.type = "audio/mpeg"; temp.src = path + snd[i] + ".mp3" + "?r=" + rand; } //temp.preload = "auto"; console.log('after canplaythrough event set'); } } My concern is...if I am doing this, and adding a variable to the end of the sound file...wouldn't it be ignoring the cached file and downloading the entire file again when I try to play it in my game? Link to comment Share on other sites More sharing options...
astralaaron Posted November 9, 2013 Author Share Posted November 9, 2013 ahhh sounds are driving me crazy.... in internet explorer it seems as if the sounds download every time it is fired...so even a little 1 second sound file downloads (status 200) each time you click on something in the game...so in IE it delays about 1 second before firing each sound.... Link to comment Share on other sites More sharing options...
Ingolme Posted November 10, 2013 Share Posted November 10, 2013 Just create one <audio> element for each sound that will be in the game. Keep a pointer to that audio element the whole time and simply call the play method when you need to. No need to create a new audio element to play a sound if another audio element already has it. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now