Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Preload of MP3 files from XML

New Here ,
Aug 25, 2009 Aug 25, 2009

Hey guys,

I've almost finished my flash website for a friend and just want to add a simple MP3 player.

I have the following code which reads an XML file and loads the mp3s referred to in it and plays them... this is all cool...(i've removed the bits for the buttons as i didnt think they were relevant)

what I really really want to be able to do is buffer the MP3 files so that they begin playing when 1/2 loaded or similar (ideally preload 1/2 of track 1, play track 1, when track 1 loading is complete start preloading track 2 etc.)

I just cant work out how to do it...

Any advice would be very gratefully received!

var my_songs:XMLList;

var my_total:Number;

var my_sound:Sound;

var my_channel:SoundChannel;

var current_song:Number = 0;

var song_position:Number;

var song_paused:Boolean;

var myXMLLoader:URLLoader = new URLLoader();

myXMLLoader.load(new URLRequest("playlist.xml"));

myXMLLoader.addEventListener(Event.COMPLETE, processXML);

function processXML(e:Event):void {

var myXML:XML = new XML(e.target.data);

my_songs = myXML.SONG;

my_total = my_songs.length();

playSong(0); // Simply remove this line to stop automatic playback.

myXMLLoader.removeEventListener(Event.COMPLETE, processXML);

myXMLLoader = null;

}

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

}

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

TOPICS
ActionScript
2.4K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 25, 2009 Aug 25, 2009

you can use a progressevent to detect when the mp3 is 1/2 loaded.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 25, 2009 Aug 25, 2009

Hey, thanks for the prompt reply,

I was trying to go that route but think I am doing something very silly (i havent used flash before... last website i did was director ;p)

here's what i tried... (at this point i was just trying to get a dynamic txtbox called "bytes" to display how many bytes of the file had loaded - i figured once i got that variable updating correctly I could go from there)

any pointers?

all code is as before other than the playsong function:

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

}

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

this.loaderInfo.addEventListener(

  ProgressEvent.PROGRESS, MP3_LOADING

);

function MP3_LOADING(event:ProgressEvent):void {

  var loaded:Number=my_sound.bytesLoaded

  bytes.text=int(loaded)+"%";

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 25, 2009 Aug 25, 2009

sorry missing a right brace in the code below (at the end of the MP3Loader function)... still the same issue though!

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

}

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

this.loaderInfo.addEventListener(

  ProgressEvent.PROGRESS, MP3_LOADING

);

function MP3_LOADING(event:ProgressEvent):void {

  var loaded:Number=my_sound.bytesLoaded

  bytes.text=int(loaded)+"%";

}

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 25, 2009 Aug 25, 2009

i'm not sure what you're trying to do with that code but, if you want to start your sound when it's 1/2 loaded, you should use something like:

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

}

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

this.loaderInfo.addEventListener(

  ProgressEvent.PROGRESS, MP3_LOADING

);

var alreadyStarted:Boolean=false;

function MP3_LOADING(e:ProgressEvent):void {

  var loaded:Number =e.bytesLoaded;

var total:Number=e.bytesTotal;

  bytes.text=int(loaded*100/total)+"%";

if(loaded*2>=total&&!alreadyStarted){

alreadyStarted=true;

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 25, 2009 Aug 25, 2009

hey dude,

I tried that and it's not working...

it shows the track name/artist name etc. but nothing in the bytes box and it doesnt start playing...

(it was missing a Right Brace which i added at the bottom... dunno if that's right?)

any more advice (sorry for being such a n00b, I program quite a bit in VB and PHP and what you've done looks right so I'm struggling to see where the issue is here!)

also... where does the value for "e" come from in this code? - excuse my stupidity!

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

}

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

this.loaderInfo.addEventListener(

  ProgressEvent.PROGRESS, MP3_LOADING

);

var alreadyStarted:Boolean=false;

function MP3_LOADING(e:ProgressEvent):void {

  var loaded:Number =e.bytesLoaded;

var total:Number=e.bytesTotal;

  bytes.text=int(loaded*100/total)+"%";

if(loaded*2>=total&&!alreadyStarted){

alreadyStarted=true;

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

}

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 25, 2009 Aug 25, 2009

you should not need the extra bracket unless you're nesting functions.  and you should never nest named functions.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 25, 2009 Aug 25, 2009

Ok,

I checked my code and I did have the MP3LOADING function inside the playsong function (d'oh)

I've split them up as below...

I'm now getting the bytes text box displaying 100% straight away (i guess this is possible as im testing locally on my pc not with a remote server... BUT im also getting the error: "TypeError: Error #1009: Cannot access a property or method of a null object reference.

at mp3_fla::MainTimeline/MP3_LOADING()" and no music...

I'm sure I'm still doing something very stupid!

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

}

}

this.loaderInfo.addEventListener(

  ProgressEvent.PROGRESS, MP3_LOADING

);

var alreadyStarted:Boolean=false;

function MP3_LOADING(e:ProgressEvent):void {

  var loaded:Number =e.bytesLoaded;

var total:Number=e.bytesTotal;

  bytes.text=int(loaded*100/total)+"%";

if(loaded*2>=total&&!alreadyStarted){

alreadyStarted=true;

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 25, 2009 Aug 25, 2009

click file/publish settings/flash, tick "permit debugging" and retest.  the line number with the problem will be displayed in the error message so you can, more easily, debug your code.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 25, 2009 Aug 25, 2009

Awesome, I was going to say there isnt much help with debugging 😜

i'm getting an error at frame1:48 which i assume is line 48:

TypeError: Error #1009: Cannot access a property or method of a null object reference.

at mp3_fla::MainTimeline/MP3_LOADING()[mp3_fla.MainTimeline::frame1:48]

which is:

my_channel = my_sound.play();

I guess its saying either my_channel or my_sound are null right? but they're both being set in the stage before in the following statements:

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

}

so I dont know how either can be null at that point?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 25, 2009 Aug 25, 2009

some place in your code (outside those functions) should be:

var my_channel:SoundChannel;

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 25, 2009 Aug 25, 2009

I already have that at the top of my actionscript with t'other variables heres the whole lot:

var my_songs:XMLList;

var my_total:Number;

var my_sound:Sound;

var my_channel:SoundChannel;

var current_song:Number = 0;

var song_position:Number;

var song_paused:Boolean;

var myXMLLoader:URLLoader = new URLLoader();

myXMLLoader.load(new URLRequest("playlist.xml"));

myXMLLoader.addEventListener(Event.COMPLETE, processXML);

function processXML(e:Event):void {

var myXML:XML = new XML(e.target.data);

my_songs = myXML.SONG;

my_total = my_songs.length();

playSong(0); // Simply remove this line to stop automatic playback.

myXMLLoader.removeEventListener(Event.COMPLETE, processXML);

myXMLLoader = null;

}

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

}

my_sound = new Sound();

my_sound.load(new URLRequest(myURL));

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

next_btn.addEventListener(MouseEvent.CLICK, onNext);

function onNext(e:Event):void{ //This used to have MouseEvent, change it to Event.

current_song++;

if (current_song>=my_total){

current_song=0;

}

playSong(current_song);

}

prev_btn.addEventListener(MouseEvent.CLICK, onPrev);

function onPrev(e:MouseEvent):void{

current_song--;

if (current_song<0){

current_song = my_total-1;

}

playSong(current_song);

}

pause_btn.addEventListener(MouseEvent.CLICK, onPause);

function onPause(e:MouseEvent):void{

if (my_channel){

song_position = my_channel.position;

my_channel.stop();

song_paused=true;

}

}

play_btn.addEventListener(MouseEvent.CLICK, onPlay);

function onPlay(e:MouseEvent):void{

if (song_paused){

my_channel = my_sound.play(song_position);

song_paused=false;

} else if (!my_channel){

playSong(current_song);

}

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 25, 2009 Aug 25, 2009

remove my_sound = new Sound(); in playSong() and create your new sound where you currently declare my_sound:

var my_sound:Sound=new Sound();

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 25, 2009 Aug 25, 2009

thanks for the help but I now have another error :*(

slightly different error:

ArgumentError: Error #2068: Invalid sound.

at flash.media::Sound/play()

at mp3_fla::MainTimeline/MP3_LOADING()[mp3_fla.MainTimeline::frame1:47]

line 47 is "my_channel = my_sound.play();"
var my_songs:XMLList;
var my_total:Number;
var my_sound:Sound=new Sound();
var my_channel:SoundChannel;
var current_song:Number = 0;
var song_position:Number;
var song_paused:Boolean;
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
function processXML(e:Event):void {
var myXML:XML = new XML(e.target.data);
my_songs = myXML.SONG;
my_total = my_songs.length();
playSong(0); // Simply remove this line to stop automatic playback.
myXMLLoader.removeEventListener(Event.COMPLETE, processXML);
myXMLLoader = null;
}
function playSong(mySong:Number):void{
var myTitle = my_songs[mySong].@TITLE;
var myArtist = my_songs[mySong].@ARTIST;
var info = myTitle+" - "+myArtist;
var myURL = my_songs[mySong].@URL;
title_txt.text = info;
if (my_channel){
my_channel.stop();
my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);
//my_sound = new Sound();
my_sound.load(new URLRequest(myURL));
}
}
this.loaderInfo.addEventListener(
  ProgressEvent.PROGRESS, MP3_LOADING
);
var alreadyStarted:Boolean=false;
function MP3_LOADING(e:ProgressEvent):void {
  var loaded:Number =e.bytesLoaded;
var total:Number=e.bytesTotal;
  bytes.text=int(loaded*100/total)+"%";
if(loaded*2>=total&&!alreadyStarted){
alreadyStarted=true;
my_channel = my_sound.play();
my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);
}
}
next_btn.addEventListener(MouseEvent.CLICK, onNext);
function onNext(e:Event):void{ //This used to have MouseEvent, change it to Event.
current_song++;
if (current_song>=my_total){
current_song=0;
}
playSong(current_song);
}
prev_btn.addEventListener(MouseEvent.CLICK, onPrev);
function onPrev(e:MouseEvent):void{
current_song--;
if (current_song<0){
current_song = my_total-1;
}
playSong(current_song);
}
pause_btn.addEventListener(MouseEvent.CLICK, onPause);
function onPause(e:MouseEvent):void{
if (my_channel){
song_position = my_channel.position;
my_channel.stop();
song_paused=true;
}
}
play_btn.addEventListener(MouseEvent.CLICK, onPlay);
function onPlay(e:MouseEvent):void{
if (song_paused){
my_channel = my_sound.play(song_position);
song_paused=false;
} else if (!my_channel){
playSong(current_song);
}
}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 25, 2009 Aug 25, 2009

how large is that mp3?

and use trace(myURL) to see if the output is what you expect.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Aug 26, 2009 Aug 26, 2009

What I've understood from from your problem is that you want to show the progress of a streaming sound file. If that is the case the n you should check this link from adobe help: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7d25.html

Here in the "Monitoring the sound loading process" they have mentioned how to work with the progress of loading large files into the application.

COMPLETE event doesn't works fine in case of streaming large files.

In addition to that, http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7d22.html explains how you can preload a part of the song and then start playing it.

Hope this helps..


Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 26, 2009 Aug 26, 2009

Hey Kglad,

There are 3 files around 5MB each (they'll be smaller when i publish the site, im just testing with dummy mp3s from my itunes library atm)

I'll try the trace thing today and see what it says...

Hey rjoshicool,

Thanks for that, I'll have a proper read of that stuff now, the feedback on the loading isnt that important (i was just trying to display it to check that the rest of the code was working properly), I just wanted to preload 50% of the mp3 file before playing then hopefully preload the next mp3 file in the playlist in the background while the first one played

dan

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 26, 2009 Aug 26, 2009

Hey guys,

I read the adobe stuff and tryed the following code...

It wont play any music and doesnt show anything in the bytes text box!

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

title_txt.text = info;

var myURL = my_songs[mySong].@URL;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

my_sound.addEventListener(ProgressEvent.PROGRESS, onLoadProgress);

my_sound.addEventListener(Event.COMPLETE, onLoadComplete);

my_sound.addEventListener(IOErrorEvent.IO_ERROR, onIOError);

my_sound.load(new URLRequest(myURL));

}

}

function onLoadProgress(event:ProgressEvent):void

{

    var loadedPct:uint = Math.round(100 * (event.bytesLoaded / event.bytesTotal));

    trace("The sound is " + loadedPct + "% loaded.");

bytes.text=int(loadedPct)+"%";

}

function onLoadComplete(event:Event):void

{

// trace(myURL);

    var localSound:Sound = event.target as Sound;

    localSound.play();

}

function onIOError(event:IOErrorEvent)

{

    trace("The sound could not be loaded: " + event.text);

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 27, 2009 Aug 27, 2009

hey kglad,

baaa. ignore my last couple of posts, I had something stoopid in my code.

I've got the following code in the mp3 loading function (I've changed it a bit just to test it)

the bytes textbox shows the bytes loaded / total bytes then when its 100% loaded it displays "PLAYME" so its definitely hitting the if statement.. but it wont play the song.

function MP3_LOADING(e:ProgressEvent):void {

var loaded:Number =e.bytesLoaded;

var total:Number=e.bytesTotal;

//  bytes.text=int(loaded*100/total)+"%";

bytes.text=int(loaded)+" / "+(total)

//if(loaded*2>=total&&!alreadyStarted){

if(loaded==total){

bytes.text=("PLAYME!!!");

alreadyStarted=true;

my_channel = my_sound.play();

my_channel.addEventListener(Event.SOUND_COMPLETE, onNext);

}

}

Dan

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 27, 2009 Aug 27, 2009

use the complete event to trigger the start of your sound.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 27, 2009 Aug 27, 2009

sorry to be so clueless... i know what you mean but not how to do it..

I've tried something like this:

function MP3_LOADING(e:ProgressEvent):void {
var loaded:Number =e.bytesLoaded;
var total:Number=e.bytesTotal;
bytes.text=int(loaded)+" / "+(total)
if(loaded==(total/2)){
bytes.text=("PLAYME");
alreadyStarted=true;

my_channel.addEventListener(Event.SOUND_COMPLETE, playme);
}
}

function playme(e:Event):void

my_sound.play();
bytes.text=("HITTING PLAYME");

but it doesnt like this... it gives me an error about missing a right brace at a completely unrelated part of my code (i.e. on another layer in a different frame!)

I assume i'm doing something fundemantally wronge here...

does this line : "my_channel.addEventListener(Event.SOUND_COMPLETE, playme);" mean when the event completes goto playme?

and then i need a function called playme which does the my_sound.play(); command?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 27, 2009 Aug 27, 2009

not the soundcomplete event, the complete event of your loader.  use the onLoadComplete() function that you had a few messages above.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 28, 2009 Aug 28, 2009
LATEST

Along these lines?

It's not hitting the new Complete event though..

function playSong(mySong:Number):void{

var myTitle = my_songs[mySong].@TITLE;

var myArtist = my_songs[mySong].@ARTIST;

var info = myTitle+" - "+myArtist;

var myURL = my_songs[mySong].@URL;

title_txt.text = info;

if (my_channel){

my_channel.stop();

my_channel.removeEventListener(Event.SOUND_COMPLETE, onNext);

my_sound.load(new URLRequest(myURL));

}

}

this.loaderInfo.addEventListener(

  ProgressEvent.PROGRESS, MP3_LOADING

);

my_sound.addEventListener(Event.COMPLETE,onLoadComplete);

var alreadyStarted:Boolean=false;

function MP3_LOADING(e:ProgressEvent):void {

var loaded:Number =e.bytesLoaded;

var total:Number=e.bytesTotal;

//  bytes.text=int(loaded*100/total)+"%";

bytes.text=int(loaded)+" / "+(total)

//if(loaded*2>=total&&!alreadyStarted){

if(loaded==(total)){

bytes.text=("PLAYME");

alreadyStarted=true;

}

}

function onLoadComplete(event:Event):void

{

bytes.text=("LOADED");

    var localSound:Sound = event.target as Sound;

    localSound.play();

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines