SoundManager 2: Seamless Looping MP3s in Flash (Demo)
Eureka! Here's a feature people have been asking about for years with SoundManager 2, progress has finally been made. ;) This is for AS3/Flash 9+ and also applies to regular Flash development, so read on if you have wanted seamless playback there too.
Maybe this isn't new to some, but I'd never been able to find anything previously that worked. The solution I've found involves encoding gapless MP3s and preloading the sound.
The Flash Sound Looping Problem
Historically, Flash has always seemed to have trouble looping dynamically-loaded MP3 sounds. Seamless looping of the sound appears to be impossible because of gaps introduced in the MP3 file, and perhaps from other unknown Flash weirdness. (Flash movies made in the Flash IDE with "embedded"/linked sounds don't suffer this problem, for whatever reason.)
Tip #1: Use AS3's native Sound.play(offset, loops)
Rather than try to handle onfinish() events and loop yourself, the trick is to specify the number of loops in the native Flash sound API play(offset, loops) method - and secondly (and most importantly,) creating a "gapless" MP3 file; that is, one which does not contain any empty data frames at the end. MP3 is encoded as frames, or blocks of sound, and it never rounds off quite right to make a seamless sound unless your sound has a perfectly-divisible number of samples. Thus, in most cases you'll have a gap of space presumably at the end of your sound.
Tip #2: Encode "gapless" MP3 by feeding the loop into itself
Using the free "LAME" MP3 encoding software, I made this loop seamless as such:
lame -b 128 -h --nogap loop.wav copy-of-loop.wav
(You will end up with two MP3 files in this case, the first should be the seamless one.)
LAME's "nogap" encoding feature is described as "gapless encoding for a set of contiguous files" - ie., making Pink Floyd's "Dark Side Of The Moon" play track 1 to track 2 without silence in-between. However for the looping case, what if I were to use the same track for both?
.. That is, creating the "no gap" version of the MP3 using the same file for sound #1 and sound #2. Put another way, the end is the beginning; any empty space in #1 gets filled with #2.. So, the end of sound #1 leads into the beginning of sound #2. That is the crucial difference which makes seamless looping - I think - work, even if it now means there is a small slice of duplicated samples.
Tip #3: Preload the MP3, play after onload()
Finally, I found that preloading the whole sound before playing it seems to make truly-seamless playback actually work. It seems to be "close, but not quite" if you simply start playing the sound without preloading.
Thus, the API call for SoundManager 2 boils down to something like this:
This is quite nice as I've been wanting "native" seamless audio playback in Flash without having to write my own audio decoder etc. and subsequently re-writing the whole audio API, for years.
This was introduced on the v2.95b.20100323+DEV branch of SM2 on GitHub, and is included in current releases. See www.schillmania.com/projects/soundmanager2/ for the latest and greatest.