AS3: Caching Sound, Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful.

by troy on September 25, 2007

Sound object is a single use item. Once it's been loaded you can't use it again, regardless if it's the same mp3 or a different one, or null, you'll get the cryptic error "Functions called in incorrect sequence"

Example: do this:

s = new Sound(req);

///do a bunch of stuff, and at some time later try to load a new mp3 in
s.load(req);

You will get

Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful.

For each new mp3 you need to create a new Sound object. Note that SoundChannel is like a playhead, more than one of them can be accessing the Sound data, so you can create chorus/echo effects by triggering play() multiple times at different time/offsets. Here's a sound player that cycles through 2 mp3s with no errors, and caches the results.

import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.*;
import com.troyworks.core.persistance.CacheEvent;

var mp3s:Array = ["test.mp3","BT - Satellite.mp3"];

var cache:Object = new Object();

playNext_mc.addEventListener(MouseEvent.CLICK, playSound);

var s:Sound;
var _channel:SoundChannel;

function getNextAudioURL():String {
var curURL:String = mp3s.shift();
mp3s.push(curURL);
return curURL;
}
function playSound(evt:Event = null) {
var audioSwfURL:String = getNextAudioURL();
trace("***************************************************************");
trace("playSound " +audioSwfURL);
//trace(" attempting to restore " + audioSwfURL + " into AUDIO");
try {
if (_channel != null) {
//_channel.stop(); //UNCOMMENT ME TO STOP THE PREVIOUS PLAYING TRACK
//s.load(); //won't work with progressive
//s.close(); //won't work with progressive
}
if (audioSwfURL != null && cache[audioSwfURL] == null) {

//////////// normal audio loading ////////////
var req:URLRequest = new URLRequest(audioSwfURL);
s = new Sound();
//speaker_mc.display_txt.text =".";
s.addEventListener(Event.COMPLETE, onSoundLoaded);
s.addEventListener(IOErrorEvent.IO_ERROR, onSoundFailedToLoad);
s.load(req);
}else{

//////////// use cached audio ////////////////
trace("hitting cache");
var cevt:CacheEvent = new CacheEvent(Event.COMPLETE);
cevt.target = cache[audioSwfURL];
onSoundLoaded(cevt);
}
} catch (err:IOError) {
trace(err.toString());
} catch (err:Error) {
trace(err.toString());
}
}

function onSoundFailedToLoad(Event:IOErrorEvent):void {
trace("onSoundLoaded **FAILED**");
//speaker_mc.display_txt.text = "!";
}
function onSoundLoaded(event:Event ):void {
//speaker_mc.display_txt.text = "";

var localSound:Sound = event.target as Sound;

////////////// parse the key mp3 name /////////////////

//NOTE: a cleaner approach way would to be a Proxy that passes arguments along with the event, created during //the listener

var url:String = localSound.url;
var a:Number = url.lastIndexOf("/");
var b:Number = url.lastIndexOf("\\");
var c:Number = Math.max(a,b);
var url2:String = url.substr(c+1, url.length);
trace("onSoundLoaded" + url2);

//////////// cache it ////////////////////////
cache[url2] = localSound;
_channel = localSound.play();
localSound.addEventListener(Event.SOUND_COMPLETE, onPlayComplete);

}
function onPlayComplete(evt:Event):void {
//if has more sounds play them else, move to next slide
//content_mc.play();
}
playSound();

Caching Sounds...or anything for that matter

Once you've loaded a Sound(Bitmap etc) it's in memory so if your reusing it (e.g. Sound FX) there's no need to reload it. Here you can use a  cache, using the name of the sound as a key, and a CustomEvent to mimic the loaded event, as the default Event target is readonly, so you can't mimic the call coming from the cache. The solution is to override it, and call the listeners directly if you can't redispatch using the original sound.  The advantage is the loading event, don't know the difference between the real or loaded. The cache might also be used for offline/online type activities. But of course be aware you're memory useage for caching like this can get large quickly.

package com.troyworks.core.persistance {
import flash.events.*;
public class CacheEvent extends Event {

private var _overriddenTarget:Object;

public function CacheEvent(type:String,bubbles:Boolean=false, cancelable:Boolean=false) {
super(type, bubbles, cancelable);
}
override public function get target():Object{
return _overriddenTarget;
}
public function set target(target:Object):void{
_overriddenTarget = target;
}

}

}

{ 1 trackback }

Error #2037: Functions called in incorrect sequence, or earlier call was unsuccessful. « Richard Hart - Interactive Developer
April 11, 2008 at 5:55 pm

{ 5 comments… read them below or add one }

David May 11, 2009 at 6:52 pm

Thanks!

A little nit-pick…could you make future posts with tabbed code? It’s just easier on the eyes. You also have some your/you’re confusion, which bothers us grammar nazis :)

troy May 11, 2009 at 7:20 pm

Dude, I’m looking for grammar nazi, you for hire?

Yeah I prefer tabbed pages too. Wordpress occasionally mangles, things.
I’m lucky I have time to post much, and between typing at 140wpm and speed reading I make tons of errors. My goal is to get the content out where it can help. Which I think I’m doing.

I plan on getting a better code plugin, pretty printing, code highlighting, easy to copy and paste. If you have a plugin you recommend let me know.

John Morton September 22, 2009 at 10:50 am

I’m so happy you posted this. I kept trying to reuse a sound object and didn’t interrupt the error message to mean what you’ve smartly pointed out here. Thank you!

Yss March 4, 2010 at 1:43 pm

so i am having this same error. i having a play button and a stop button. The play button plays my audio and then the stop button stops it but then I can’t press the play again. i get the error. I want to be able to play the audio, stop it and then replay it by pressing the play button.

troy March 4, 2010 at 5:35 pm

This isn’t a paid support site :) but look into SoundChannel and Sound.play to get it working.

Leave a Comment

Previous post:

Next post: