Seamless Audio Loops with Flash

Most of the games that we create use looping audio, either for music or as a sound effect. One of the limitations of the MP3 audio format is that it adds a fraction of a second of silence at the beginning of a file. For most audio this is tolerable and imperceptible, however, if you need a perfect loop for something like music, then you’re going to have to find a better solution.

MP3 Waveform

We looked at all the alternatives that searching Google had to offer (i.e., special exporting software, fancy AS3 runtime code, etc) and after all this it seemed the best solution was also the easiest. If you import raw audio such as a WAV or AIF file into Flash Professional and embed the sound into your SWF (either as a timeline loop or with an exported class), it will not add the previously mentioned bit of silence. We call these undocumented Flash gems, “Flash magic”.

This is good news except that it’s a pain to manually import each audio file into an FLA and then export if all you need is a SWF. We created a Flash plugin (also called extensions or commands), which automates this process. Select a raw audio file, choose the bit rate and file name, then presto, SWF created. No need to save an intermediary FLA or fuddle with publish settings. The SWF file that’s been created is special in that it only contains a single Sound object with a class name that matches the file name. For instance, if the SWF file name is “gameplayMusic.swf” there would be a single AS3 Sound object with a class name “gameplayMusic” inside the SWF. We can then create a special loading utility for these types of sounds (see AS3 code below).

The only downside to this method is that you can no longer stream in the audio, which would save on up-front loading. Instead, the entire SWF needs to be preloaded before you can have access to the Sound object.

The Generate Audio Loop tool can be downloaded from the secret Tools section of our website.

Here is a sample utility for loading the Sound object.
[cc lang="actionscript3"]package com.cloudkid.util
{
import flash.media.Sound;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.Event;

/**
* Utilities for dealing with sounds
* @author Matt Moore
*/
public class SoundUtils
{
/**
* Load a sound for an external SWF
* @param The path to the SWF file to load
* @param The callback when the sound has been loaded
* @param The name of the sound class (defaults to filename without “.swf”)
*/
public static function loadExternalSound(url:String, callback:Function, className:String=null): void
{
if (className == null)
{
className = url.substring(
url.lastIndexOf(“/”),
url.lastIndexOf(“.”)
);
}
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(
Event.COMPLETE,
function(ev:Event): void
{
var s:Sound;
try
{
var clazz:Class = loader.contentLoaderInfo.applicationDomain.getDefinition(className) as Class;
s = new clazz;
}
catch(e:Error)
{
trace(“Error: class doesn’t exist ‘” + className + “‘ in ‘” + url + “‘”);
}
callback(s);
}
);
loader.load(new URLRequest(url));
}
}
}
[/cc]

And a sample implementation:
[cc lang="actionscript3"]function onSoundLoaded(sound:Sound): void
{
if (sound == null)
{
trace(“Unable to load sound”);
return;
}
sound.play();
}
SoundUtils.loadExternalSound(“drive.swf”, onSoundLoaded);[/cc]