AS3 - Working with Sound.
The other day I was writing a small AIR mp3 player for myself that I could use for simply putting on shuffle and letting play all day. All that I wanted was to create a small AIR app that I could load my mp3 library into, read the ID3 tags, and implement my own custom search function. Once I had it all running I opened it up and let it scan my Music folder for mp3’s. Of course, loading the ID3 info for 3000+ mp3 files took a little while so I just left my computer and came back a little while later. When I came back my computer had been rendered almost useless! When I looked at the Activity Monitor it was showing that “adl” was using almost 1.5GB of my ram!
So naturally I thought to myself, “Geesh, stupid me. I must of left my event listeners on the Sound class”, which would mean that the Flash Player would not garbage collect them properly, thus leaving all the sound data in memory. After fixing this issue I let app scan my library again. Once again, rendering my computer useless.
After a long time searhing the internet for blog posts, documentation etc on this issue I came across nothing that showed me how to “unload” a sound from memory. Once the sound was loaded, it seemed that it was in memory until you closed your application. After finding nothing to help me out, I started to change my code around, trying different methods of loading / reading the ID3 info. Then I stumbled upon this, “the delete keyword deletes the actual variable definition, not just the variable’s value. This of course frees any reference it was holding, potentially freeing that object for garbage collection”.
So, I created a class that dynamically created properties to hold loaded Sound classes, and used the delete keyword to remove or “unload” the sounds. Bingo! The sounds were now unloading properly and my app then only started to consume 30 - 40 MB of ram while scanning my library.
Here is the key to the solution:
private var dynamicProps:Array = [null, null];
private function get sound():Sound {
return dynamicProps[0];
}
private function set sound(value:Sound):void {
destroySoundChannel();
destroySound();
System.gc(); //force garbage collection
dynamicProps[0] = value;
addSoundListeners();
dispatchEvent(new Event("soundChanged"));
}
private function destroySound():void {
if ( dynamicProps[0] != null ) {
//cancel any remaining downloading
try {
Sound(dynamicProps[0]).close();
} catch ( e:Error ) {}
removeSoundListeners();
delete dynamicProps[0];
dynamicProps[0] = null;
}
}
private function destroySoundChannel():void {
if ( dynamicProps[1] != null ) {
SoundChannel(dynamicProps[1]).stop();
removeSoundChannelListeners();
delete dynamicProps[1];
dynamicProps[1] = null;
}
}
Here is an example, of reading the ID3 tags of 100 mp3 files:

Not using “SoundManager” to load mp3’s

Using the “SoundManager” class for loading mp3’s
Here is an example usage of SoundManager.as
var manager:SoundManager = new SoundManager();
private function loadSound(url:String):void {
manager.addEventListener(Event.COMPLETE, soundLoaded);
//we can call loadSound as many times as we like
//everytime we call it the old sound is replaced by the
//new loading sound.
manager.loadSound(new URLRequest(url));
}
private function soundLoaded(e:Event):void {
manager.play();
}
private function soundComplete(e:Event):void {
loadSound("anotherSound.mp3");
}
Files: