Copy link to clipboard
Copied
I have written a loadSound function which handles loading and playing multiple sounds. This function works fine when I call this function in another keyframe i.e. the frame in which the function is not written. But when I call the function on the same frame in which the function is written the sounds gets mixed up. For example the function is written in 1st keyframe. If I call this function in 2nd, 3rd and 4th keyframe (with different sounds) it works fine. But when i call the same function in 1st, 2nd and 3rd keyframe it all gets messed up.
In 1st keyframe the sound plays properly. When I move to 2nd Keyframe the 2nd sound plays. But when I move back to the 1st keyframe the 2nd and 1st keyframe sounds all get mixed up. This doesn't happen when I call the function in 2nd, 3rd and 4th keyframes.
Below is my function:
import flash.events.Event;
import flash.media.Sound;
import flash.net.URLRequest;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.errors.IOError;
import flash.media.SoundChannel;
import flash.media.SoundMixer;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.display.MovieClip;
import flash.media.SoundTransform;
stop();
var s:Sound;
var localSound:SoundChannel = new SoundChannel();
var req:URLRequest;
var loadedPct:uint;
var currentFrameArr:Array = ["One","Two","Three"];
var urlArr:Array = ["sound/m01_t01_s01.mp3","sound/m01_t01_s02.mp3","sound/page10_11.mp3"];
function loadSnd(currentFrm:String)
{
s = new Sound();
s.addEventListener(ProgressEvent.PROGRESS, onSoundProgress);
s.addEventListener(Event.COMPLETE, onSoundLoaded);
s.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
localSound.stop();
for (var i:uint=0; i<currentFrameArr.length; i++)
{
if (currentFrm == currentFrameArr)
{
req = new URLRequest(urlArr);
}
}
s.load(req);
function onSoundProgress(evt:ProgressEvent):void
{
loadedPct = Math.round(100 * (evt.bytesLoaded / evt.bytesTotal));
trace("The sound is " + loadedPct + " % loaded");
}
function onSoundLoaded(evt:Event):void
{
localSound = s.play();
}
function onIOError(evt:IOErrorEvent):void
{
trace("The sound could not be loaded: " + evt.text);
}
}
Call to this function in different frames:
loadSnd("One");
loadSnd("Two");
etc
If I pass the parameter 'One' in loadSnd it plays the 1st element in urlArray, 'Two' 2nd element and so on.
I have been scratching my head since long over this.
Can anybody please pinpoint the error.
Copy link to clipboard
Copied
Never nest functions.
take
function onSoundProgress(evt:ProgressEvent):void
{
loadedPct = Math.round(100 * (evt.bytesLoaded / evt.bytesTotal));
trace("The sound is " + loadedPct + " % loaded");
}
function onSoundLoaded(evt:Event):void
{
localSound = s.play();
}
function onIOError(evt:IOErrorEvent):void
{
trace("The sound could not be loaded: " + evt.text);
}
out of the loadSNd() and see where that gets you
Copy link to clipboard
Copied
Done. Still getting the same error. Strange its working fine in the next keyframes but when i call the function in which the function is written the sound is getting messed up.
Any other helpful suggestions.
Copy link to clipboard
Copied
another source of errors is your loop:
for (var i:uint=0; i<currentFrameArr.length; i++)
{
if (currentFrm == currentFrameArr)
{
req = new URLRequest(urlArr);
// to leave the loop when the condition is met use
break();
}
}
since you have no break() statement in it, even when your condition is true
it will run to the end anyway,
so if the currentFrm var is updating somehow while the loop runs
it will overwrite your previous result
Copy link to clipboard
Copied
Included the break; statement as well. Again the same error. But if I include the soundChannel.stop() in my buttons it works fine though. Athough I would have liked to be embedded it within the function itself as I am planning to write a class file for this to be included in my project. Below code if included works just fine.
nextBtn.addEventListener(MouseEvent.CLICK, onNextClk);
function onNextClk(evt:MouseEvent):void
{
localSound.stop();
this.nextFrame();
}
prevBtn.addEventListener(MouseEvent.CLICK, onPrevClk);
function onPrevClk(evt:MouseEvent):void
{
localSound.stop();
this.prevFrame();
}
I was also thinking what would happen if the frame is changed without a mouseclick for example if an animation ends and a new keyframe starts and I would like to include a different sound file in that keyframe.
If the soundChannel.stop() is included in the function itself no matter whatever event occurs either a mouse click on a button or a animation end it would stop the previous sound and play a new one.
Copy link to clipboard
Copied
Got the solution. The SoundMixer.stopAll(); statement did the trick. The complete workable function is pasted below:
import flash.events.Event;
import flash.media.Sound;
import flash.net.URLRequest;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.errors.IOError;
import flash.media.SoundChannel;
import flash.media.SoundMixer;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.display.MovieClip;
import flash.media.SoundTransform;
stop();
var s:Sound;
var localSound:SoundChannel = new SoundChannel();
var req:URLRequest;
var loadedPct:uint;
var currentFrameArr:Array = ["One","Two","Three"];
var urlArr:Array = ["sound/m01_t01_s01.mp3","sound/m01_t01_s02.mp3","sound/page10_11.mp3"];
function loadSnd(currentFrm:String)
{
s = new Sound();
s.addEventListener(ProgressEvent.PROGRESS, onSoundProgress);
s.addEventListener(Event.COMPLETE, onSoundLoaded);
s.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
SoundMixer.stopAll();
localSound.stop();
for (var i:uint=0; i<currentFrameArr.length; i++)
{
if (currentFrm == currentFrameArr)
{
req = new URLRequest(urlArr);
break;
}
}
s.load(req);
}
function onSoundProgress(evt:ProgressEvent):void
{
loadedPct = Math.round(100 * (evt.bytesLoaded / evt.bytesTotal));
trace("The sound is " + loadedPct + " % loaded");
}
function onSoundLoaded(evt:Event):void
{
localSound = s.play();
}
function onIOError(evt:IOErrorEvent):void
{
trace("The sound could not be loaded: " + evt.text);
}
Calling the function
loadSnd("One");
loadSnd("Two"); etc
Copy link to clipboard
Copied
You only have one localSound variable, so when you overwrite it with another SoundChannel, you can no longer control any other sounds. localSound is written to from an asynchronous process, but the way you call stop() assume that your logic is blocking.
Try storing an array or vector of all sounds that are playing, then discard any that have been stopped. This allows you to control all of them.