Article
The Flash Anthology: Cool Effects & Practical ActionScript - Chapter 5: Sound Effects
XML, MP3, and ID3 Tag Reader
This effect uses the same choir sound clips we used previously in this chapter, but with a slightly different approach. We'll import a playlist from an XML file and load the MP3 files dynamically into Flash. We'll also present song information (including Album, Artist, and Song Title) that's stored within the MP3 in what are called ID3 tags, as shown in Figure 5.5.

Figure 5.5. Create a random MP3 player using XML and ID3 data.
ID3 tag information is referenced differently in Flash MX than in Flash MX 2004, owing to the differences between versions of Flash Player. Macromedia Flash Player 7 supports the latest ID3 v2.2 and v2.4 tags. As the data is stored at the beginning of the MP3 file, this information is referenced immediately upon opening the MP3 stream. On the other hand, Macromedia Flash Player 6 supports only ID3 v1.0 and v1.1 tags, which are stored at the end of the file. On that platform, we must wait until the stream is fully loaded before we can retrieve the ID3 tag information.
We'll initially create an MP3 player for version 6 of the Flash Player, supporting ID3 v1.x tags. Then, we'll modify the effect to take advantage of ID3 v2.x tag support within version 7 of the Flash Player.
To edit this effect, locate mp3–mx.fla in the code archive.
It uses several MP3 files: choir1.mp3, choir2.mp3, choir3.mp3, choir4.mp3, and choir5.mp3. We'll also be needing the XML file that acts as the playlist; it's called playlist.xml and can also be found in the code archive.
Setting the Scene
For this project, we need a clickable movie clip that loads a random MP3 file and a dynamic text field that displays the ID3 data from the MP3 file.
- Create a new Flash document that's 500 pixels wide and 450 pixels high. Accept the default frame rate and click OK.
- Rename the default layer Actions and add beneath it two new layers named Interface and Background.
- Select the first frame of the Interface layer and create a movie clip called
PlayRandomButtoncontaining a button that's approximately 70 pixels high and 70 pixels wide. Name the instance randomplayer and move the clip to the left of the stage centre, as shown in Figure 5.5. - Create a new, 320x160 pixel dynamic text field to the right of the button. Name the field
trackID3Info. - In the Property Inspector for the new field, click the Character… button and choose Basic Latin (or All Characters in Flash MX).
- Add to the first frame of the Background layer a rectangle that frames the text area you just created.
- Save your work.
- Locate the files
choir1.mp3,choir2.mp3,choir3.mp3,choir4.mp3andchoir5.mp3from the code archive and move them into the same folder in which you saved the document. - Type the following code into a text editor and save it as
playlist.xmlin the same folder. - Select the first frame of the Actions layer and add the following code to the Actions Panel:
- Save your document and preview your work.
- Select the first frame of the Actions layer, then locate and delete the
playTrackfunction from the Actions Panel. It's no longer needed! - Replace the onPress event handler code for the
randomPlayermovie clip with the following code: - Save and preview your work.
We'll use this clip to randomly load an MP3 file and pass the ID3 tag information from the MP3 file into a dynamic text field.
This dynamic text field will act as a container that receives the ID3 tag information from the dynamically loaded MP3 files.
Now, for a little window-dressing:
You can add as many extras as you wish to increase the aesthetics of the interface. Refer to Figure 5.5 for inspiration!
Creating the XML Playlist
We now need to create the XML playlist that references the MP3 files we're planning to load.
Tip
For more information on working with XML, see Introduction to XML, by Harry Fuecks.
Example 5.11. playlist.xml Actions : 1
<?xml version="1.0" encoding="iso-8859-1"?>
<playlist>
<mp3file track="choir1.mp3"/>
<mp3file track="choir2.mp3"/>
<mp3file track="choir3.mp3"/>
<mp3file track="choir4.mp3"/>
<mp3file track="choir5.mp3"/>
</playlist>
Unlike HTML, which uses a predefined set of tags, XML allows you to create custom data structures. As long as all opening tags have a matching closing tag (or, as in the case of the mp3File tag in this example, they close themselves), Flash will import the data structure as an ActionScript XML object, allowing you to manipulate and access the information contained within the file.
This XML file is structurally simple. The playlist tag is the top-level node, and the mp3file tags are its child nodes. These child nodes also contain an attribute called track, which holds the name of the MP3 file we wish to pull into Flash.
Our ActionScript will import this XML file and move through the data structure, populating an array with the names of the MP3 files it contains.
Adding the ActionScript
Example 5.12. mp3–mx.fla Actions : 1 (excerpt)
var tracklist = new Array ();
var mp3List = new XML ();
mp3List.ignoreWhite = true;
mp3List.onLoad = createPlayList;
mp3List.load ("playlist.xml");
function createPlayList (success)
{
if (!success)
{
return;
}
var topLevel = null;
for (i = 0; i <= this.childNodes.length; i++)
{
if (this.childNodes[i].nodeValue == null &&
this.childNodes[i].nodeName == "playlist")
{
topLevel = this.childNodes[i];
break;
}
}
if (topLevel != null)
{
for (i = 0; i <= topLevel.childNodes.length; i++)
{
if (topLevel.childNodes[i].nodeName == "mp3file")
{
var track =
topLevel.childNodes[i].attributes["track"];
_root.tracklist.push (track);
}
}
}
}
function randomBetween (a, b)
{
return Math.min (a, b) + random (Math.abs (a - b) + 1);
}
function playTrack ()
{
var track = _root.track;
if (track.getBytesLoaded () == track.getBytesTotal () &&
track.duration > 0)
{
clearInterval (_root.checkLoaded);
trackID3Info.text = "";
trackID3Info.text += "Title: " + track.id3.songname +
newline;
trackID3Info.text += "Artist: " + track.id3.artist +
newline;
trackID3Info.text += "Album: " + track.id3.album +
newline;
trackID3Info.text += "Year: " + track.id3.year + newline;
trackID3Info.text += "Comments: " + track.id3.comment +
newline;
}
}
randomplayer.onPress = function ()
{
stopAllSounds ();
var trackNo = randomBetween (0, _root.tracklist.length - 1);
_root.track = new Sound ();
_root.track.loadSound (_root.tracklist[trackNo], true);
_root.checkLoaded = setInterval (playTrack, 500);
};
Let's break this code into manageable chunks and see what's going on.
First, we create an empty array to contain our list of MP3 tracks.
var tracklist = new Array ();
Next, we create an XML object called mp3List, and set its ignoreWhite property to true so that line feeds and whitespace aren't parsed as separate nodes.
var mp3List = new XML ();
mp3List.ignoreWhite = true;
We then set the event handler that will execute when the XML file has loaded (createPlayList) and load the data from playlist.xml.
mp3List.onLoad = createPlayList;
mp3List.load ("playlist.xml");
Now we define the createPlayList function, which gets called to handle the XML data once it has loaded.
function createPlayList (success)
{
if (!success)
{
return;
}
var topLevel = null;
for (i = 0; i <= this.childNodes.length; i++)
{
if (this.childNodes[i].nodeValue == null &&
this.childNodes[i].nodeName == "playlist")
{
topLevel = this.childNodes[i];
break;
}
}
The first thing we do is check whether the XML file loaded successfully, as indicated by the success parameter. If it didn't, we bail out before attempting to process it.
We then enter a for loop based on the number of top-level nodes within the XML object (this). We check these nodes until we find the one that has a null nodeValue, meaning it's a tag (as opposed to a piece of text) and that its name is playlist. This node is stored in a variable named topLevel. We then break out of the for loop.
Next, we enter another for loop, in order to examine its children:
if (topLevel != null)
{
for (i = 0; i <= topLevel.childNodes.length; i++)
{
if (topLevel.childNodes[i].nodeName == "mp3file")
{
var track = topLevel.childNodes[i].attributes["track"];
For each of the child nodes, we check to see if it's an mp3file tag, and then populate a variable with the track attribute of the tag, which is the name of an MP3 file.
Finally, we populate the tracklist array using its push method to add the filename to the start of the array.
_root.tracklist.push (track);
That takes care of building the playlist. Now, when the randomplayer movie clip is clicked, the following code is brought into play:
randomplayer.onPress = function ()
{
stopAllSounds ();
var trackNo = randomBetween (0, _root.tracklist.length - 1);
_root.track = new Sound ();
_root.track.loadSound (_root.tracklist[trackNo], true);
_root.checkLoaded = setInterval (playTrack, 500);
};
First, we stop all currently running sounds using the stopAllSounds function. We then populate a variable called trackNo with a random number in order to choose one of the tracks in our tracklist array.
We then create a new Sound object and load it up with a random MP3 file using the trackNo variable we have just populated.
Finally, we use the setInterval function to call the playTrack function every half-second. We store the interval identifier in a variable called checkLoaded in the root of the movie so we can cancel it when appropriate.
Now, all that's left to discuss is the playTrack function:
function playTrack ()
{
var track = _root.track;
if (track.getBytesLoaded () == track.getBytesTotal () &&
track.duration > 0)
{
clearInterval (_root.checkLoaded);
trackID3Info.text = "";
trackID3Info.text += "Title: " + track.id3.songname + newline;
trackID3Info.text += "Artist: " + track.id3.artist + newline;
trackID3Info.text += "Album: " + track.id3.album + newline;
trackID3Info.text += "Year: " + track.id3.year + newline;
trackID3Info.text += "Comments: " + track.id3.comment +
newline;
}
}
Each time this function is called, we check whether the MP3 file has loaded successfully. Once it has, we cancel the interval that is set to call the function every half-second with the clearInterval function. We can then populate the trackID3Info dynamic text field with the ID3 tag information from the MP3 file.
ID3 v1.x Caveat
As Flash Player 6 and Flash MX support only ID3 v1.0 and v1.1 tags, we have to make sure that the MP3 file is completely loaded before we attempt to pull the ID3 tag information from it. This is essential, as the ID3 tag data is found at the end of the MP3 file.
In Flash MX 2004, which can produce content for Flash Player 7 and supports the ID3 v2.2 and v2.4 tag information located at the beginning of the MP3 file, this information is much more easily accessed. We'll see what this means to Flash developers when we modify this example.
When the movie loads, the XML file is imported and the tracklist array is populated with all the track information from the playlist.xml file. Clicking on the randomplayer movie clip loads an MP3 file and displays its ID3 tag data in the dynamic text field.
Modifications
As we discussed before, it's much easier to reference ID3 tag data in Flash Player 7. This Player supports v2.2 and v2.4 ID3 tags, which are stored at the beginning of the MP3 file rather than at the end.
Flash MX 2004 only!
As you can only produce Flash Player 7 SWF files using Flash MX 2004, this modification is suitable for Flash MX 2004 only.
To edit this effect, locate mp3–mx2004.fla in the code archive.
We need only make a couple of simple modifications to the movie to allow Flash MX 2004 to read ID3 v2.2 and 2.4 tag information.
Example 5.13. mp3–mx2004.fla Actions : 1 (excerpt)
randomPlayer.onPress = function ()
{
stopAllSounds ();
var trackNo = randomBetween (0, trackInfo.length - 1);
var track = new Sound ();
track.onID3 = function ()
{
trackID3Info.text = "";
trackID3Info.text += "Title: " + track.id3.TIT2 + newline;
trackID3Info.text += "Artist: " + track.id3.TPE1 + newline;
trackID3Info.text += "Album: " + track.id3.TALB + newline;
trackID3Info.text += "Year: " + track.id3.TYER + newline;
trackID3Info.text += "Comments: " + track.id3.COMM +
newline;
};
track.loadSound (tracklist[trackNo], true);
};
This code is essentially the same as before, but it uses an event handler to process the ID3 tag information rather than calling a function every half-second to check for it.
After we've created the new Sound object (track), we reference a new event handler, called onID3, which is available in Flash Player 7. This is invoked when new ID3 data is detected for a loaded MP3 file, which means that we don't need to confirm that the MP3 file has completely loaded before we check for the ID3 tag data. Once the onID3 event handler is invoked, we can proceed to populate the trackID3Info dynamic text field with the ID3 2.0 tags. It's as simple as that!
ID3 Reference
For a complete listing of supported ID3 tags within Flash MX 2004, search for Sound.ID3 in the Help Panel.
Now, when you click the randomPlayer movie clip, the MP3 file starts to play and the ID3 tag data is displayed in the dynamic text field almost instantly. You no longer need to wait for the MP3 file to load completely as you did in the previous example.
Conclusion
Who said that all you can do with sound clips is play them? Certainly not me! I hope that we've covered enough material within this chapter to fuel your desire to create some really interesting sound-based interfaces, experimental effects, and other items.
It's now time to see what we can accomplish using video effects in Flash!
This marks the end of our series containing three chapters from SitePoint's The Flash Anthology: Cool Effects & Practical ActionScript, which contains over 60 practical ActionScript solutions for Flash developers and designers.
The book contains a total of 10 chapters that provide over 60 ActionScipted solutions to common problems in Flash. Every solution you'll ever need for your Flash projects, from text and video effects, to debugging and using external data in your applications, is covered in this 455-page reference. All the code included in the book is available in a free downloadable archive.
For more information, see the book page.