How to Pause Sound and Resume Where it Left Off
In recent entries, we examined the Sound constructor and toggling sound globally. Let’s continue in this vein and take a closer look at how to pause and resume audio. The Sound class provides two handy methods for this: Sound.stop() and Sound.start(). Thanks to these, we can wire up a button to pause a Sound instance, and another to restart it, without much effort at all …
var snd:Sound = new Sound();
snd.attachSound("bazooka");
btnHalt.onRelease = function():Void {
snd.stop();
}
btnResume.onRelease = function():Void {
snd.start();
}
… but this doesn’t resume the sound: this starts it again from the beginning. How can we start the audio from where it left off?
An answer, short and sweet
Use the optional Sound.start() offset parameter in cahoots with the Sound.position property. Assuming the above code already in place — in a keyframe of your scripts layer — change the btnResume event handler as follows.
btnResume.onRelease = function():Void {
snd.start(snd.position / 1000);
}
How it works
Sound.start() accepts two optional parameters: an offset in seconds and a number of times to loop. If you want a 5-second Sound instance to start halfway through, supply 2.5 as the first parameter, because 2.5 is half of 5.
snd.start(2.5);
Of course, in this scenario, it’s up to the user when to pause and resume, so a hard coded number won’t do. The answer rests with the Sound.position property, which tells how far along the audio has played, not unlike like the position of the arm on a record player. The value returned by this property is a number in milliseconds. Because Sound.start() expects seconds, divide this value by 1,000.
One final note
Keep in mind, the above snippet, on its own, won‘t do anything to restart an audio file that has run its course. At the end of a sound clip, the position property will naturally be equal to its duration. A more intelligent resume button, then, might actually check for this possibility and act accordingly:
btnResume.onRelease = function():Void {
if (snd.position < snd.duration) {
snd.start(snd.position / 1000);
} else {
snd.start();
}
}
October 31st, 2006 at 12:10 am
As I am not very advanced in Flash, I rely a lot on simple explanations and code I can copy and paste and cook together for my needs. This little gem saved my day after hours of frustrating trial and error and searching on the web. Thank you so very much - now I can finally begin with my flash based storyboard
October 31st, 2006 at 8:23 am
mStudios,
Terrific! Glad to hear it. Best of luck as you continue exploring.
December 6th, 2006 at 5:39 am
David, u the bomb!!!
December 7th, 2006 at 7:44 am
HI David!!!
How do I create a resume functionality in Flash? I want the user to quit the programme, but when they come back, they should be able to start where they left off.
December 7th, 2006 at 2:04 pm
Fezile,
For that, you need a way to store information somewhere other than the user’s memory. Flash provides an AS2 class just for this purpose, the
SharedObjectclass. Check it out!December 13th, 2006 at 1:58 am
DAvid,
What is the main difference between square1.x = 20 and square1._x = 20 when you are dynamically positioning movieclips on stage? Why would the one with underscore work, whilst the one without underscore doesn’t work. Because the sysytem accepts both of them but will just not work. When and how do you know which one to use to achieve the best result?
December 14th, 2006 at 8:53 pm
____ ____ ____ _________ ____ ____ ____ _________ ____
||y |||o |||u ||| |||a |||r |||e ||| |||a ||
||__|||__|||__|||_______|||__|||__|||__|||_______|||__||
|/__\|/__\|/__\|/_______\|/__\|/__\|/__\|/_______\|/__\|
____ ____ ____ ____ ____ ____ ____
||g |||e |||n |||i |||u |||s |||! ||
||__|||__|||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|/__\|/__\|
December 15th, 2006 at 8:31 am
To bj,
Thanks! But I think that compliment is more than I deserve.
To Fezile,
The main difference between
_xandxdepends on entirely on what class that property belongs to. Between those two, theMovieClipclass, which is what you’re describing, only features_x, soxis simply a property that doesn’t exist — unless you create it yourself (theMovieClipclass is dynamic, so you can add properties as you like, which in the case of movie clips are effectively variables on their timelines).The underscore is a historical throwback. In ActionScript 3.0, the
MovieClipclass simply goes byxnow for horizontal positioning.To get the full scoop, I recommend you spend some time in the “
MovieClipclass” entry of the ActionScript 2.0 Language Reference. It shows you all the properties, methods, and events available to all movie clip instances.December 28th, 2006 at 3:54 pm
What about if you are streaming a sound dynamically? Does the sound have to be attached using the object.attachSound in order to control playback positioning?
Thanks,
Vinney
December 28th, 2006 at 9:28 pm
Vinney,
The functionality of the
Soundclass works across the board. Once the audio is playing, whether it’s attached or loaded, you may monitor its progress with theSound.positionproperty and control playback positioning by using the optionalsecondsOffsetparameter of theSound.start()method. Of course, if you’re loading the sound from an external source, you’ll have to make sure it’s fully loaded first.If you’re truly streaming the sound — that is, if you’re loading the audio from Flash Media Server — then you’d use the Flash-Media-Server–specific
NetStreamclass. There, too, you would be able to seek to the desired position in the audio stream.January 9th, 2007 at 2:24 pm
Just came across this luckily for me, it has saved me a lot of grief and time writing oodles of bad code trying to get the same effect. Thanks, the short and sweet answer really shows that you know what you are doing, Thanks again.
March 7th, 2007 at 4:32 pm
That was so simple I nearly crapped myself…
Been playing with the doofus pause button in my project fer days…
I feel like a dork.
I mean DAYS! Honestly!!
Thanks, you’re a Flash God…
March 7th, 2007 at 4:50 pm
Baz and Emilia,
Thanks!
March 8th, 2007 at 5:50 pm
Couple follow-ups here.
1. “…truely streaming…”? What do you mean by “truely”? Just because I set the isStreaming argument to “true” doesn’t mean I’m truely streaming?
2. “Flash Media Server…” Is a Flash Media Server something special? If so, how do I know if the website has one?
3. What do you mean by the external media is “fully loaded”? I’ve got a 1.25 hour mp3 file on a website that appears to start immediately when called. Is it fully loaded when it’s able to play? Or something else.
Thanks.
March 8th, 2007 at 7:04 pm
Red Rojo,
That’s right. If you don’t have a streaming server actually sending the file, then you’re only providing a progressive download. In many regards, they amount to the same thing. GIFs and JPGs can progressively download, for example — in good old HTML, I mean — … it’s a useful mechanism that allows the user to begin experiencing the file before it fully loads.
Flash Media Server is indeed something special, and it’s expensive.
Because it’s progressively downloaded (or streaming, depending on your server configuration), that MP3 starts playing when only a few kilobytes have been downloaded.
March 8th, 2007 at 10:52 pm
Hmm…. I don’t think I could ever fully load my sound file — it’s 1.25 hours long, 35MB!! So am I right that I can’t use the sound.position or sound.offset parameter if I am loading the sound from an external source? Is there another option?
March 8th, 2007 at 10:59 pm
Red Rojo,
While that is an awfully large file, it certainly will load … eventually. I can’t imagine what sort of frustrating experience that might be for dial up users, but QuickTime.com serves up video files that size every day. Even without a streaming server, that file should (in theory) start playing a few a few seconds. But I would probably break it up into a series of smaller files.
March 9th, 2007 at 9:09 am
Sure. I can certainly break up the file — it’s audio only. What’s a workable size? Would I use something like sound.onSoundComplete() to launch the next clip? Should it sound seemless — or might there be delays between clips? Could I then use the sound.position property to pause/resume? Feasible approach?
March 11th, 2007 at 9:31 pm
Red Rojo,
Workable size is totally subjective. If you’re sure your visitors have cable, 35MB wouldn’t be out of the question. If you break it up, then yes, the
Sound.completeevent could trigger each subsequent file. If you used theSound.load()method to load each piece, there would be a slight delay between each clip. The only way to avoid that would be to preload each clip at least one audio file at a time. TheSound.positionwould restart from zero for each new file.March 22nd, 2007 at 4:06 pm
David-
Thanks for all the Flash info…It’s helped me alot. However I have an issue that maybe you could explain. I’ve put the action script that you supplied for stopping and resuming sound and it works great only after the second time the user clicks the start button. In other words, the first time the user clicks the play button after sound has been stopped, it goes back to the beginning. The next time they click on the play button after it has been stopped, it resumes from the exact point that it stopped. Any idea what might be going on? Here is what I used as far as the action script:
var song_sound:Sound = new Sound();
song_sound.attachSound(”Slide1sound”);
Stop_Movie_btn.onRelease = function(){
song_sound.stop();
}
Play_Movie_btn.onRelease = function(){
song_sound.start(song_sound.position / 1000);
}
Thanks in advance.
Rick
March 22nd, 2007 at 8:44 pm
Rick,
Interesting. Honestly, I can’t imagine why you might encounter what you’ve described, given your code. On its own, the
Sound.start()method starts from the beginning — but the optional parameters allow that default behavior to change. It’s possible that something in yoursong_sound.position / 1000expression is somehow returning a value of zero, or maybeNaN(Not a Number). You could try usingtrace()to check …… that’ll let you see what you’re actually feeding in as a parameter.
March 24th, 2007 at 3:55 pm
David-
Thanks for replying so quickly. I did the trace and the first time I clicked on the Play button, it showed a zero in the Output window. Every subsequent time, it showed the appropriate postion where I restarted. I’m authoring this on a Mac. Do you think that it might be a Mac vs PC type of thing?
Rick
March 24th, 2007 at 5:02 pm
David-
OK, so I think the problem is that you assumed I actually knew what I was doing. I didn’t. Though I had created a sound object and attached the sound, I hadn’t told it to start playing. I had actually put the sound onto the timeline. So when I Stopped the sound and then clicked the Play button, that was actually the first time the attached sound started playing, thus the “0″ in the Output window when I did the Trace. So now, I have gone and put in the Start command in each one of my slides, removed the sound files from the timeline, and everything works perfectly. Sorry to waste your time, David. I really do appreciate your blog, however. It is and awesome resource, as are you. Thanks again!
Rick
March 25th, 2007 at 5:47 pm
Rick,
Ha! No worries. I’m actually really happy for you that you figured it out.
Good stuff!
May 1st, 2007 at 9:22 am
Thank you, thank you. This little script has saved me time, frustration and my sanity. May you live long and prosper.
June 24th, 2007 at 11:14 am
Hey David,
This tutorial helped me a little but it’s not working for my website.
The following code that I have works well for the stop and play button
Let me describe what I have here. the “stopMusic” and “startMusic” are my buttons instances and “loops” is the instance for the music clip. However if i want to use this code for pausing the music it won’t work
June 27th, 2007 at 10:40 pm
Gabriel,
In your first set of code,
loopsmust be a movie clip, because you’re invoking aMovieClipmethod (i.e.gotoAndStop()) on the instance name.In the second batch,
loopshas somehow become aSoundinstance — because you’re invokingSoundproperties (position,duration) and a method (start()) on it. My hunch is that your problem is spelled out right there. For any of this to work,loopsmust be an instance of theSoundclass. Does that make sense?June 28th, 2007 at 9:11 am
Hey David,
Thanks for responding. The “loops” instance is a MovieClip. The stop and play function does work but the pause doesn’t.
June 28th, 2007 at 9:15 am
Gabriel,
The stop and play part works because you’re using
MovieClipfunctionality on a movie clip. I’m guessing that you’ve placed audio into frame 2 of theloopsclip, and that frame 1 contains no audio. So that makes sense: what you’ve got is an old school way of toggling sound in Flash.Because
loopsis a movie clip symbol, you can’t performSoundfunctionality on it. If you want to use the technique discussed in this blog entry, you’ll have to get rid ofloopsaltogether. Use ActionScript to attach or load your audio. That’s when your audio becomes an instance of theSoundclass, and that’s when you can invoke methods on it like the ones in the article.July 11th, 2007 at 11:26 am
Hi,
I am developing a sound on/off functionality in Actionscript 3.0. I have sound directly on the timeline and the property of the sound is Streaming. I have created a sound object and tried to set the volume = 0. But sound does not stop.
July 12th, 2007 at 12:43 pm
Tejasvita,
If you look up the
Soundclass in the ActionScript 3.0 Language and Components Reference, you’ll find that the new version no longer supports aSound.stop()method. That explains why comparable ActionScript 2.0 samples won’t work the same way. Where did thatstop()method go? It’s now part of a companion class,SoundChannel. In AS3, if you want to further control audio once it plays, you need to associateSound.play()with aSoundChannelinstance.July 31st, 2007 at 3:57 pm
Hi David,
Great tutorial! I definitely was able to absorb the new knowledge and grasp the concepts quite easily.
I have a general question. I want to achieve the exact same thing (stopping a sound and then resuming it form that exact position), however my sounds are all on the timeline. By using the stop() command to stop the SWF playhead (and stopAllSounds(), to stop the playback of my sounds) I am able to effectively “pause” the playback of my SWF. This is great, until I attempt to resume the playback. Using the play() command resumes the playback of the SWF file, but the sound does not resume playback. It does not even start from the beginning again. Do you know of any way around this, or do I pretty much have to remove the sound from the timeline and use a Sound Object to control the position, as you’ve demonstrated in the tutorial above?
Many thanks in advance, keep the good advice coming!
-Jeff
August 5th, 2007 at 8:19 pm
Jeff,
What you’re describing is a by-product of using movie clip timelines, rather than
Soundinstances, to manipulate sound in Flash. If the audio files in your timelines have their Sync property set to Event (see the Property inspector for the audio in a given keyframe) then any sound on that keyframe is loaded all at once into memory. Stopping the timeline under such circumstances is not enough to stop the audio, which is why the additional call tostopAllSounds()is necessary; after all, the sound is already loaded into memory. Restarting the playhead fails to restart the audio in that case because, again, the sound has already loaded and was stopped.If the Sync property is set to Stream, then the audio files are locked in-step with the timeline they’re in. In that case, stopping and starting the timeline will synchronize the audio’s stopping and starting. It’s worth a shot, and that’s the only way I can think of to restart audio that is embedded in a timeline. Otherwise, you’d have to send the playhead — even if only momentarily — back to the keyframe into which the audio is first embedded.
August 9th, 2007 at 9:14 pm
Nice one this is what i need instead of playing from the beginnig. That gets annoying after a few time.
August 10th, 2007 at 8:48 am
Free Loops,
Thanks!
August 22nd, 2007 at 11:12 am
Hi David,
Thanks for the response. I tried setting my sounds to Stream, and when I pause the timeline, of course the sound pauses as well. But when I resume the timeline, the movie resumes but the sounds do not
Oh well it was worth the shot.
Thanks for the advice!
August 22nd, 2007 at 11:20 am
Jeff,
If a sound file is embedded in a timeline and set to Stream, that sound will stop and start up again as the timeline does, I promise.
I just made a test file. New FLA, imported an MP3 and dragged it to frame 1 of Layer 1, set it to Stream, and increased the timeline as long as necessary to play the whole file. Created a quick button, gave it the instance name
btn, and used the following event handler:That works for me. Granted, it’s not at all the approach illustrated in the original blog entry, but it’s definitely one of the “old school” ways of starting and stopping sound in Flash.
September 9th, 2007 at 3:49 am
Hi David, In my swf im pausing the audio when another movie clip is loaded and on frame out I need it to resume play. So the only part not explained already is how to detect a frame exit ? I’ve searched for this but people always offer a walk around and never say if its possible and if so could you give an example? Please and Thank you ^^
September 16th, 2007 at 11:11 pm
Thanks! going crazy with that!
Works great with tell targets to stop(ish) and play a little equalizer animation (moving music bars)!!!
var mySound:Sound = new Sound();
mySound.loadSound(”01 Tamacun.mp3″, true);
mySound.onLoad = function(success) {
if (success) {
this.start();
}
};
btnStop.onRelease = function() {
mySound.stop();
tellTarget (”_root.equalizer”) {
gotoAndPlay(20);
}
};
btnPlay.onRelease = function() {
if (mySound.position
September 16th, 2007 at 11:12 pm
Here’s the rest of that!
btnPlay.onRelease = function() {
if (mySound.position
September 18th, 2007 at 9:46 am
To Lee …
If you’re using the
MovieClipLoaderclass, you could resume play on theonLoadCompleteoronLoadInitevent. I’m not sure whose onFrameOut you want to listen for, but for better or worse: a) there is noonFrameOutevent in ActionScript and b) what matters seems to be the successful load of your other movie clip.This concept simply isn’t a part of the ActionScript API. Director’s Lingo language can test for frame ins and outs, but ActionScript only looks for frame enters (essentially frame ins).
If you’re looping in conjunction with a
MovieClip.onEnterFrameevent, you can use that in conceptually the same way as the idea of a frame out. (I’m not sure if you’re looping in order to determine when the other SWF has loaded.)See if “How to Tell When an External SWF has Fully Loaded” helps you out any.
MovieClipLoaderis likely your easiest solution.To Amber …
Glad you’re having fun with it!
Woo hoo!
October 4th, 2007 at 6:14 am
Thanks for the feedback David! The site in question has background music (A). It also has another movie clip that has its own background music(B). When the user selects to play an embedded movie with background music(B) thats when I pause music from (A). Since theres no OnFrameOut (needed for when movie clip is closed or replaced) I put “ins” on every possible selection option so no matter your next move (unless your move is to do nothing) the music(A) will resume when u click a button. Of course using many “ins” to cover one “out” is not efficient and I’m still looking for a better way =/ any ideas? Thanks in advance!
October 5th, 2007 at 1:23 pm
// Initializers and such
var pauseStatus:Number = 1;
var themeSound:Sound = new JeopardyTheme();
var themeSoundChannel:SoundChannel = themeSound.play();
var themePosition:Number = themeSoundChannel.position;
trace(”Start: ” + themePosition);
// Clicked Pause
function clickedPause(event:MouseEvent):void
{
if (pauseStatus == 1)
{
themePosition = themeSoundChannel.position;
trace(”Turn OFF:” + themePosition);
SoundMixer.stopAll();
pauseStatus = 0;
}
else if (pauseStatus == 0)
{
trace(”Turn ON:” + themePosition);
themeSound.play(themePosition);
pauseStatus = 1;
}
}
pause_mc.addEventListener(MouseEvent.CLICK, clickedPause);
First trace: 0
Okay, first trace is good.
Click the pause button for the FIRST time (to pause):
Turn OFF: 3912.134679258
Okay, so far so good.
Click the pause button for the SECOND time (to play):
Turn ON: 3912.134679258
Okay, again we’re good. Now watch this.
Click the pause button for the THIRD time (to pause again):
Turn OFF: 3912.134679258
Huh? Why didn’t the position advance?
October 5th, 2007 at 1:41 pm
Did some messing around and here’s the answer.
// Sounds
var themeSound:Sound = new JeopardyTheme();
var themeSoundChannel:SoundChannel = new SoundChannel();
themeSoundChannel = themeSound.play();
var themePosition:Number = themeSoundChannel.position;
var pauseStatus:Number = 1;
// Clicked Pause
function clickedPause(event:MouseEvent):void
{
if (pauseStatus == 1)
{
themePosition = themeSoundChannel.position;
themeSoundChannel.stop();
pauseStatus = 0;
}
else if (pauseStatus == 0)
{
themeSoundChannel = themeSound.play(themePosition);
pauseStatus = 1;
}
}
pause_mc.addEventListener(MouseEvent.CLICK, clickedPause);
Everything works beautiful.
October 8th, 2007 at 3:48 pm
To Lee …
I’m afraid I can’t envision what you’re describing. If you’re loading external content — what you’re calling “an embedded movie with background music(B)” — then you’ll obviously be loading that external content by some means (maybe
MovieClipLoader, maybe theloadMovie()function, maybe theMovieClip.loadMovie()method …) and whenever you’re doing that loading, that’s when you’ll turn down the volume of the main music. When you then choose to load other external content, that’s when you’ll configure the audio again — either to bring up the volume of the main music again or to leave it as is.I’m trying to understand what you mean by “I put ‘ins’ on every possible selection option,” but I’m coming up dry! Maybe these “embedded movies” aren’t external(?). When you describe a movie clip as “closed or replaced,” what ActionScript function/method are you using to do that closing or replacing — and wouldn’t that be the same area of code you’d use to determine the volume of the main audio?
To Ean …
Hey, glad you worked out a solution!
The key, in this case (that is, ActionScript 3.0, which differers from the ActionScript 2.0 in the article), is that you must re-associate the
SoundChannelinstance with the theSound.play()method, as you’ve done in your second post:themeSoundChannel = themeSound.play(themePosition);October 27th, 2007 at 4:51 pm
Thanks for your responses again David! When they click to watch this code is run
on (release) {
_root.myMusic.stop();
loadMovie(”mov.swf”, “_root.ani.mov”);
}
The “ins” and “outs” were lingo someone else in the blog was using (thought it was u) so i just went with it
“Closed or Replaced” there is a close button where if they click the movie clip closes and the back ground music comes back on (an example on an “in”) the movie clip is usualy replaced by other buttons which also load swf files into the same movie clip replacing it (another example of an “in”)
loadMovie(”mov2.swf”, “_root.ani.mov”);
It would be nice if instead of having to add lines in every button that replaces or closes the movie clip if i could just have a line in the movie clip that said when i get closed or replaced unpause the background music. (an example of an “out”)
I hope this clears up what I am wanting to know. If you would like I can link the exact page in question.
Thanks again David.
October 27th, 2007 at 9:12 pm
Lee,
You could certainly use ActionScript to programmatically attach a Close button — the same Close button — to each loaded SWF. That way, you would only have to write that button’s code once. I’m not sure if you have a separate button for each external SWF (inside each SWF, say) but if you do, I agree that duplicating so much code would be tedious. By using dot syntax to assign your event handlers (see the “Museum Pieces” article), you would potentially free yourself from some — possibly much — of that duplication.
Have you looked into the
MovieClip.onUnloadevent handler? You could attach an event handler to the movie clip that acts as your container for the incoming content (_root.ani.mov).October 31st, 2007 at 1:20 am
You’re a life saver. Watch it go into play @ www.rebbeccacorry.com
October 31st, 2007 at 2:21 pm
Alright, I’m using AS 2.0 and trying to get the timeline and sound to stop and start back together. However, a simple stop (); command doesn’t stop the timeline as precisely as my sound stops. I know I’ve butchered the code, but it was all in an attempt to make the two stop together so forgive me. Can you tell me how I can get the two stopping and starting together? Aside from embedding the sound and using streaming audio. Streaming audio just won’t work for this movie because precise timing is required and I can’t have dropped bits of the audio if the load doesn’t work quickly enough.
Here is the code.
soundTest = new Sound();
soundTest.attachSound(”Finalizeaudio”);
soundTest.start();
clipLength.text = soundTest.duration/1000+” s”;
rootTime=_root();
movieLength.text=rootTime.duration/1000+”s”;
pauseClip.onPress = function() {
pausePositionS = soundTest.position/1000;
soundTest.stop();
stopRootS=rootTime.position/1000;
rootTime.stop();
};
startClip.onPress = function() {
if (soundTest.position == soundTest.duration) {
soundTest.start();
} else {
soundTest.start(pausePositionS);
play();}
}
if (rootTime.position==rootTime.duration) {
rootTime.start();
}else{
rootTime.start(stopRootS);
play();
};
startClip.onEnterFrame = function() {
currentPosition.text = soundTest.position/1000;
};
The rootTime=_root is evidently pointless and not doable.
November 1st, 2007 at 2:51 pm
To Say Em …
Glad to hear it; thanks!
To Chase …
Agreed, the line
rootTime=root()doesn’t really do anything, but that doesn’t mean it couldn’t — only that setting a variable to the hypothetical return value ofroot()is meaningless unless you’ve written a customroot()function to provide the necessary object/data (there isn’t such a function natively).The main operative idea behind your code is to invoke
MovieClip.stop()andSound.stop()simultaneously when you desire both entities to stop, thenMovieClip.play()andSound.start()to resume.My hunch is that your inconsistent timeline precision is a result of a low overall timeline framerate.
November 2nd, 2007 at 11:05 am
The fps was definately a problem. Bumped it up to 24, but I’m still getting some incosistency. Will _root.position/1000 work in conjuction with the _root.play?
November 2nd, 2007 at 11:06 am
Oh and MovieClip.play() wouldn’t work for the main timeline.
November 2nd, 2007 at 11:12 am
var snd:Sound = new Sound();
snd.attachSound(”DVDtoVHSsec1″);
snd.start();
pauseClip.onPress = function() {
snd.stop();
_root.stop();
};
startClip.onPress = function() {
if (snd.position
November 2nd, 2007 at 12:02 pm
Hi David,
I’m loading external swf files into movieclips on my main Flash timeline. I use this type of code:loadMovie (”myMovie.swf”, “loader1_mc”). The movies load and play great. My problem is that although I am able to pause content on the main timeline of my Flash movie, I cannot pause these external swf files. I have tried giving the movie clips instance names and even referring to these directly in the code of the navigation, but haven’t had any success. Do you have any ideas for me?
November 3rd, 2007 at 10:38 am
To Chase …
This may just be a case of “them’s the brakes,” unfortunately. It sounds like your increased FPS helped a bit, but not enough. As it happens, I develop presentations fairly often in which the main timeline (or any movie clip timeline) needs to be halted in coordination with audio — even external audio — and in my own experience, I haven’t run into deal-breaker inconsistencies … but maybe that’s just luck?
Your question about
_root.position/1000hinges on what_rootmeans in AS2. Though the reference can change depending on certain factors (outlined here),_rootalways points to aMovieClipinstance. Since theMovieClipclass doesn’t define apositionproperty, the expression_root.positionhas no meaning — not unless you created a numerical variable of your own namedposition.Actually, you’re already using the
MovieClip.play()method: that’s what your_root.play()means. See, everything in ActionScript may be considered an object, and objects are defined by something called classes. When you’re dealing with a dynamic or input text field, you’re dealing with an instance of theTextFieldclass.When you’re dealing with a movie clip (even the main timeline, aka
_root), you’re dealing with an instance of theMovieClipclass. Classes define properties (characteristics), methods (things the object can do), and events (things the object can react to), so when you type_root.play(), you’re invoking a movie clip method (MovieClip.play()) on aMovieClipinstance (_root).Make sense? The only class names that you reference by class name are static classes such as
Math. For example, to round a number you can useMath.round(4.5), because it makes no sense — indeed, is not possible — to create an instance of theMathclass.Your last bit of sample code got truncated, but it looks like you were on the right track. All you need here is something like this:
… though, out of personal preference, I would probably use
onReleaseoveronPress, and I would only use_rootif I knew this SWF wasn’t going to be loaded into another SWF at runtime.To Faith …
How are you trying to pause these loaded SWFs? You said you’ve tried giving them instance names, but when you load a SWF into some container movie clip (e.g. your
loader1_mc), that container becomes your reference. In other words, the instance name that sounds is the instance name you’re using as the target in yourloadMovie()call.November 5th, 2007 at 9:19 am
Thanks for the link to the _root page. It helped a lot. What is another object name for the main timeline? I would like to use some other method than _root. Do I just use stop();? and play();?
November 5th, 2007 at 7:12 pm
Chase,
As you’ve seen now,
_rootcan indeed be a useful reference to the main timeline, under the circumstances outlined in the other article. In a single-SWF movie,_level0refers to that same timeline. If you want to “roll your own” reference, you can do something like this:var timelineReference:MovieClip = this;
… in a keyframe script that’s in the main timeline. From that point forward, the arbitrarily named variable
timelineReferencewill point to the main timeline, even if the current SWF is loaded into another SWF.But you touched on an idea that leads toward the very best approach: namely, an understanding of scope. Check it out. In this quick snippet …
… you already know that
_rootrefers to the timeline that containspauseClip. If you were to drop that prefix altogether …… the scope of the
MovieClip.stop()method, as shown, belongs topauseClipbecause that function is associated withpauseClip’sonPressevent. In other words, without_root— or some other object reference — you’re tellingpauseClipitself to stop.When the function executes, it thinks to itself, “Okay, I’ve got two things to do here: a) invoke
Sound.stop()on thissndinstance, whatever it is, and b) invokeMovieClip.stop()on … hmmm … well, there’s no reference prefix, so I guess I’ll just apply it to myself. I’m aMovieClipinstance, after all. Yup, that makes perfect sense; I can do that. I have no idea whatsndis, so I guess I’ll look up the chain. Aha, in the timeline above me, I see asndobject, so I guess that’s the one this function means.”Scope causes an object to look inside itself first for any object references. (Note, while ActionScript 3.0 also features this notion of scope, event handlers are scoped differently from how I’m describing here. This answer of mine is strictly geared toward ActionScript 2.0, which is what we’re using.)
A quick look at the
MovieClipclass (ActionScript 2.0 Language Reference) shows me that all movie clips feature a_parentproperty. Bingo! That’s useful. TheMovieClip._parentproperty points to the parent object/timeline of the current movie clip. Therefore, check it out …That handles it beautifully — assuming
pauseClip’s immediate parent is the main timeline.January 29th, 2008 at 11:27 pm
Hey Dave,
Great website! Thanks for all the helpful info. But I am stuck on a sound issue… I have a website template i’m making thats playing a background sound file from a seperate .SWF file thats being called. It has a play and stop button that uses this code:
on (release) {
gotoAndStop(2);
}
on (release) {
_parent.eqq.gotoAndPlay(”pl”);
_root.soundstatus = “off”;
}
I embeded a movie clip onto layer 1 of the website but when I click on “Stop” it stops the sound on the whole site, including the video that I have. How do I change something like this so that it only stops the music track thats playing!!?? Is it because its using _root.soundstatus=”off”;?
January 29th, 2008 at 11:40 pm
Rob,
Nah,
_root.soundstatusjust points to a custom string variable you have in_root. The “trick” to what you’re after depends entirely on how you’re constructing yourSoundinstance. If you omit the optional parameter in the expressionnew Sound();, then yourSoundinstance references the whole movie. On the other hand, if you pass in a reference to a particular movie clip (new Sound(someClip);), you can control the volume of that clip only — which may very well be the clip that contains your loaded content. Choice is yours.See “Understanding the Sound Constructor (AS2)” and “How to Toggle Sound Globally (AS2)” for details on how this phenomenon plays out in AS2.
Part of the problem might be your
_rootreference, too — not because of the name of thesoundstatusvariable, but simply because_rootcan be problematic if you don’t understand fully how it works. See if “Is _root Evil?” helps you decide for yourself.January 30th, 2008 at 8:43 am
Hey Dave thanks for the quick reply. Right now, my music track is a movie clip thats being loaded into level 2 when the site loads like this:
loadMovieNum(”music1.swf”,2);
I did look through your global sound blog..so is it possible to set that movie file to a “new sound();” variable and then control the volume of that specifically using my button with something like this:
on (release) {
_parent.eqq.gotoAndPlay(”pl”);
globalVolume.setVolume(0);
}
?? How would you set music1.swf as a new sound when the site initially loads up??
January 30th, 2008 at 9:07 am
Rob,
The
loadMovieNum()function loads SWFs into levels, rather than movie clips. Even so, these levels (_level0 [the default], _level1, _level2, etc.) are movie clips. Since the whole of _level2 is your container, you’ll have to use_level2as the target for yourSoundconstructor. That should do it, but I’ve never tried it. In that case, you may want to choose to name your variable something else, such as:If, for some reason, that doesn’t work, you could use one of the other approaches for loading a SWF at runtime (the
loadMovie()function, theMovieClip.loadMovie()method, or theMovieClipLoaderclass). Those load content into movie clip containers — that is, an empty (or not) movie clip symbol, with an instance name, on the Stage — so the container clip’s instance name would be your target.January 30th, 2008 at 8:58 pm
Dave,
Unfortunatley _level2.soundstatus=”off”; did not work…although that would of been sweet!
I could not get the other method you explained to work either:
I loaded the music like this:
var mymusicVolume:Sound = new Sound(_level2);
loadMovieNum(”music1.swf”, 2);
Then the play/stop button said:
on (release) {
_parent.eqq.gotoAndPlay(”pl”);
mymusicVolume.setVolume(0);
}
But No luck! I guess i’ll have to look into how the other runtime loading methods you gave me work…unless you have another suggestion…but I dont know why the last idea you provided didnt work…hmph..thanks
January 30th, 2008 at 9:35 pm
Rob,
Honestly, the
soundstatusthing may or may not be related to what you’re after. There is nosoundstatusvariable in ActionScript out of the box … that’s some sort of custom programming in your file — so it doesn’t surprise me that_level2.soundstatusdoesn’t do anything.I’m disappointed (for both our sakes!) that
new Sound(_level2)doesn’t work. I did some testing just now, and it appears that naming any level as a target forSoundis as good as naming none: it causes theSoundinstance to control the whole movie. This happens if you specify the default level (_level0), but I didn’t know that any level would do. Good to know!So … for your purposes, you’ll need to load your external content into a movie clip container, rather than a level. I still can’t say what your
soundstatusvariable is used for, but the following code succeeds as a working template:The above code assumes a movie clip symbol on the Stage with the instance name
container. TheSoundinstance is associated with that movie clip, then aMovieClipLoaderinstance uses that same movie clip as the container for the external SWF. The magic happens in theonLoadInithandler, which theMovieClipLoaderinstance (mcl) listens to. The handler changes theSoundinstance’s volume to 0 — and does so after the external SWF has loaded. That’s important. If you set the volume before or while the external content is loading, it doesn’t work.January 30th, 2008 at 11:04 pm
Hey Dave,
I have to apologize for the constant bother and for sounding dumb but I am pretty new to this and would love to get this thing to work, so I really appriciate all the help you’ve already provided!
So I used your code from above ‘as is’ to load my music file, but it doesnt play when the page is loaded. “The above code assumes a movie clip symbol on the Stage with the instance name container.” I dont know where to but this new movie clip symbol and to give it an instance. That might be why its not playing…?
And would I stop the music the same way:
Getting rid of soundstatus and using:
on (release) {
_parent.eqq.gotoAndPlay(”pl”);
loadedVolume.setVolume(0);
}
Thanks again.
January 31st, 2008 at 8:48 am
Rob,
No worries! Your questions aren’t a bother, and you don’t sound dumb at all … just new to ActionScript.
If you pasted my code literally as is, there are a number of reasons why it wouldn’t work straightaway. First, as you noted, you haven’t yet added a movie clip symbol with the instance name “container,” so let’s start with the very basics. If you start a brand new FLA — literally brand new; there’s nothing in it — and you type the following into it …
loadMovieNum("music1.swf", 2);
… then it will load the SWF file “musics1.swf” into level 2 (which is what you originally had). In order for that to work, you’d have to save this new FLA file into the same folder as music1.swf, because there’s not path information in front of that file — it’s assumed to be in the same folder.
So far, so good. You had ventured so far on your own. I’m proposing a different approach to loading that SWF, because we discovered that levels can’t be used for individualized volume control. That said, consider the
MovieClipLoaderclass. First, you need an instance of that class:All that does so far is declare an arbitrarily named variable,
mcl, and set it to the newMovieClipLoaderinstance. From this point forward, the variablemclis one instance — one working object — of theMovieClipLoaderclass. To see what functionality is available to this class, read up on its entry in the ActionScript 2.0 Language Reference. You’ll see properties (characteristics), methods (things the object can do), and events (things the object can react to). Here’s a quick example of how to load that same music1.swf with yourmclinstance, which should entirely replace the existingloadMovieNum()line:Not much to it!
The
MovieClipLoader.loadClip()method — one of the things this object can do — is invoked on themclinstance. This method accepts two parameters, just like your previousloadMovieNum()does. The first parameter is the SWF to load; the second is a movie clip to load it into.You should still be in the brand new FLA mentioned above. Your single
loadMovieNum()line should be gone, replaced with the two newMovieClipLoader-related lines. Go to Insert > New Symbol and give the new symbol a name (”container” will do). Make it a movie clip and click OK. Now you’ll see that clip in your Library. Drag it to the Stage. Because nothing is in that clip, it will appear a small white circle, which is just a placeholder. Drag that placeholder wherever you like. Wherever you do, that’s going to be where your music1.swf is loaded. If that SWF contains visual elements, their upper left corner will be the position of your container clip. You might want to put it in the upper left corner of the Stage. With this clip selected (by its little white dot), look at the Properties inspector. You’ll see where you can assign your instance name. Because the ActionScript is expected “container,” that’s what you put. (You could have used sparkleStars, but container makes sense in this case, because it describes the function of this movie clip. It doesn’t matter, by the way, that the instance name and the Library name are the same; that’s just coincidence. In reality, the two names are unrelated.)Test your movie, and the SWF will load as before. This time, it’s inside that movie clip, and you can change the position of that movie clip, animate it over time, etc., like any other.
Use that same movie clip’s instance name (
container) as the parameter in yourSoundinstance, and you should be good to go.MovieClipLoaderalso features events, and theonLoadInitevent is handled with the function I showed earlier, which lowers the volume on a particular sound instance, which I arbitrarily namedloadedVolume.Everything I’ve described stands on its own: you don’t need the
soundstatusvariable you were using before. The fact that you have a customsoundstatusvariable tells me that you have additional custom code in your previous FLA, and while that might be perfectly usable code, I have no idea what it does, so my own suggestions have nothing to do with it — and might even interfere.May 16th, 2008 at 1:01 pm
Hi David,
I am trying to find some code that would let the user of my flash presentation resume from where they left off the last time they used the presentation or start from the beginning the next time it is booted. I need a quit function that asks this question.
I have multiple modules on a desktop format and would like some code similar to what you did for sound / music.
Do you consult on this for a fee? Please let me know your thoughts.
PS. The above site is in the works and this is in an unpublished format without audio at this time. Thanks for your help.
Bob
June 4th, 2008 at 8:49 am
Hi David
Hoping this isn’t too confusing and that you can offer some advice: I am loading external SWFs into a master SWF; each external SWF has several MovieClips running in sequential order on the timeline (keypoints with named frames, i.e. seg1, seg2, etc). The MovieClips are named similarly (i.e. MCseg1, MCseg2, etc.). Each MovieClip has embedded sound. I am using an ON/OFF button for the sound, which is placed on the master SWF, and works perfectly: it is a MovieClip with two buttons, (MConOff) an ON button (frame 1) and an OFF button (frame 2), and the code respectively is:
//ON
on (release) {
gotoAndStop(2);
//moves from ON button to OFF button
_root.sndPlay.setVolume(0);
}
//OFF
on(release) {
gotoAndStop(1);
//moves from OFF button to ON button
_root.sndPlay.setVolume(100);
}
I realize this does not actually stop the sound, it in effect simply adjusts the volume to either (0) or (100). But it works for me…. and the client likes that it keeps the movie moving without sound.
My problem is not with the sound, however - it is with the MovieClips. My client wants to pause a MovieClip indefinitely (along with it’s sound), and then go back to it without interuption (restart where it left off). I created a separate MovieClip movie control (MCpausePlay) with two buttons: pause (frame 1) and play (frame 2). I coded them like this, respectively:
//pause
on (release) {
gotoAndPlay(2);
//moves from PAUSE button to PLAY button
_root.stop();
stopAllSounds();
//play
on (release) {
gotoAndPlay(1);
//moves from PLAY button to PAUSE button
_root.play();
}
This does pause the currently running MovieClip, however, the next clip loads. I need to stop the entire timeline, then restart from where I’ve stopped (by ‘timeline’ I mean the sequential MovieClips). So if I am currently running MCseg4, I want to pause it, have it wait for my click, and then start up again. As it is right now, MCseg4 does stop, but MCseg5 starts up. And I cannot get MCseg4 to restart, either.
Any Ideas?
My next challenge will be to rewind the currently running MovieClip…. any suggestions on that?
Kelley
}
June 10th, 2008 at 9:16 am
David
Though I haven’t seen a response to my query, I wanted to update you on my progress:
I managed to pause and play my MovieClip by placing the pauseBtn and playBtn within the actual MovieClip on the Actions timeline:
var snd:Sound = new Sound();
snd.attachSound(”seg1mp3″, true);
var paused = false
pauseBtn.onRelease = function():Void {
stop();
}
playBtn.onRelease = function():Void {
play();
}
However, the sound continued playing though the animation stopped. I have a sound file embedded within each MovieClip, so I did this:
pauseBtn.onRelease = function():Void {
stop();
stopAllSounds();
}
playBtn.onRelease = function():Void {
play();
snd.play();
}
The sound does not start again - what am I doing wrong here? How do I get the embedded sound file, “seg1mp3″ to resume play along with the MovieClip?
June 10th, 2008 at 10:11 am
To bob …
Apologies for the late reply! I’m working on two books at the moment, which has eaten into my time more than I had anticipated (and more than I would like to admit!).
For something like this, you’ll want to look into the
SharedObjectclass.SharedObjectis essentially the Flash Player version of browser cookies, so you can use a “Flash cookie” to store the user’s placement in the timeline (or in a sound file, or whatever) and retrieve it for later use.See if this article gets you started:
“How to Store Persistent Data with the SharedObject Class (AS2)”
… and don’t hesitate to write back if that doesn’t do it for ya.
To Kelley …
That’s a good approach, actually. In fact, it’s the approach I recommend in “How to Toggle Sound Globally (AS2).” Glad to hear that part is working for you.
I’m not quite sure I understand yet how your movie clips are laid out in the main timeline. When you say “the next clip loads,” I’m not sure what you jmean by “loads” (e.g. are you referencing external SWF files — that is, loading external content? — or are your movie clips already present in the master SWF? If you’re loading external content at runtime, you’ll have to program your buttons to interrupt the load process in addition to managing the flow of the timeline. If these movie clips are already present, you may have to reference not only the main timeline, but (perhaps) the individual timelines of your movie clips.
Both the main timeline and movie clip symbols are instances of the
MovieClipclass, which means you can invoke, for example, theMovieClip.play()method on either. TheMovieClipclass also provides astop()method and more &mdash which you’re already using, it looks like — but the difference is that you may also have to use these methods in conjunction with movie clip symbols. To do so, make sure your movie clips have instance names (you can provide one for each with the Property inspector) and precede your calls toplay()andstop()(or whatever else) with the relevant instance name. It’s identical in principle to your use ofsnd.stop(), in which you’re invoking theSound.stop()method on thesndinstance.Does that make sense?
Thanks for the follow up!
I’ve been out of state for several days at TODCon 8, so I’m behind in blog replies, but it’s great to hear you’ve continued to work through this endeavor. Good on ya!
The
stopAllSounds()function doesn’t belong to theSoundclass, and it affects all sounds in play at the time it’s called, butstopAllSounds()doesn’t give you as much control as theSoundclass.I’m not certain, for example, in what way (if at all) the
stopAllSounds()function affects theSound.positionproperty of yoursndinstance. (It’s easy enough to test, but I don’t have Flash in front of me at the moment.) In contrast, though, invokingSound.stop()leavesSound.positionwith a value you can re-use with theSound.start()method, as described in the article above.I notice you’re trying to invoke a
play()method on yoursndinstance — it’s an easy slip to make! — but theSoundclass only features astart()method.June 11th, 2008 at 9:30 am
David - thank you!
To answer you in return: the MovieClips are laid out along the timeline, one after another, within each of the external SWFs. So, for instance, I am working from the index.swf and I click the genInfo button, this loads the external genInfo.swf. This genInfo.swf has an actions layer, a mask layer and a MovieClip layer. Along the MovieClip layer are placed roughly 10 MCs in succession, separated by keyframes. The frame segments (i.e. the space along the timeline separated by keyframes) are also named, as in seg1 for MCseg1, and so on. I did this so that when I need to find a specific MC for changes, I simply scroll through the timeline to find that segment. To the user, there are no breaks in the animation; everything flows along in sync. Because the audio files in whole are quite long (some are 2 mins.) and I need to synchronize animations to the audio files, I broke each original audio file down into segments. Each segment is now 3-10 seconds long, (running at 29fps). That’s why I have so many MCs in my timelines.
Each MC contains an actions layer, an audio layer and an animations layer.
I want to be able to control each MC globally (from the index.swf), so that when I am running the genInfo.swf, I can pause and play at will without starting the animation from the very beginning. If I have to build the controls into each external swf, I’d do that - but as it is, I can only control things from the base level of the individual MovieClip. When I attempt something such as, ” _root.stop(); ” on the genInfo.swf file, this does nothing. When I script, ” stop(); ” on the actual MovieClip, however, this stops the MovieClip.
And the audio file (mp3) continues playing.
I see now after much research that there is no EASY way to pause a sound file in Flash - for whatever the technical reasoning - one must ‘fool’ the program into first stopping the sound file and recording the track position, then restarting the sound file at that exact track position. Is this correct? Sounds like a lot of scripting that I don’t understand how to do… and I have no idea where I am suppose to script this - in the individual MC, in the external swf housing multiple MCs, or in the index.swf? So far it isn’t working anywhere, so I know I’m doing something wrong because scripting is not one of my strengths; I just don’t seem to grasp the concept of how to find the track position and stop and start.
June 12th, 2008 at 8:15 am
David,
I feel like my head is going to spin around soon…. lol…
Here’s my update:
I utilized something you have on this page regarding an ‘old school’ method of pausing a sound: (using a button called, “pauseBtn”):
var paused = false;
pauseBtn.onRelease = function():Void {
if (paused) {
play();
} else {
stop();
}
paused = !paused;
}
OMG - this actually pauses sound!
HOWEVER……………… there are some problems I’ve noted:
1) I put it within a MovieClip which has an audio layer and several layers of animation. This actually paused BOTH when clicked! But, the next MovieClip along the timeline started.
2) Sound quality is terrible! It makes the audio track sound very tinny; this is a narration and the speaker’s voice sounds split in two, as if his voice is made of tin, and it has an echo made of tin. I tried changing the property to “Convert Stereo to Mono” but that made no difference
Is there a way to utilize this code to pause the currently running MovieClip AND keep the other MovieClips from running,
AND
Is there a way to adjust the sound quality once the sound is made to stream?
I feel that I am so very close to solving this problem, and yet it is still so very far out of reach…
Kelley
June 12th, 2008 at 9:02 am
Kelley,
The organization of your various SWFs, including masks, movie clips, audio layers, etc., sounds fine, complex as it may appear. When I hear “audio layer,” that suggests to me you’re embedding audio directly into your timeline(s), rather than using the
Soundclass. That’s fine too, but it’s absolutely imperative you understand the difference between using timeline sound and programmed sound.Unless you actually instantiate the
Soundclass and invoke eitherloadSound()orattachSound(), the only thing you can do with yourSoundinstance is affect the volume and panning of a particular movie clip. If you leave theSoundconstructor empty, that instance affects the main timeline (i.e., the whole SWF), which is the “toggle volume globally” technique described elsewhere on this blog. On the other hand, if you pass a movie clip reference to yourSoundinstance, you can control the volume/panning of the passed-in movie clip exclusively.It does do something — it stops the main timeline of the parent-most movie clip — but if the parent-most movie clip only has one frame and loads everything else dynamically (which is what it sounds like … I think), then stopping the main timeline doesn’t produce any visible results. All movie clips run independently of each other, so to halt the timeline(s) of loaded SWFs and/or movie clips, you’ll have to invoke
MovieClip.stop()on each individual SWF/movie clip by way of aMovieClipreference, which is usually an instance name.To be sure, ease vs. difficulty is a subjective judgment, but I believe this endeavor is easier than you realize. If your sound is attached directly to a keyframe, you can use the Property inspector to determine whether the audio’s Sync property is configured as Event or Stream.
If it’s Event, then the audio in that keyframe gets loaded into memory all at once when the playhead enters that frame. Even if you stop the playhead (
MovieClip.stop()), the audio continues to play. (This is when the standalonestopAllSounds()function can come in handy.) To get an Event sound to restart, you have to send the playhead back to the keyframe in which the audio appears, and it will start again from the beginning. In this context, there is no way to start such a sound halfway through.If your keyframe sound is set to Stream, it becomes locked in-step with the timeline, which means you don’t need the
stopAllSounds()function to halt the audio; aMovieClip.stop()method works just fine. Such audio can be started again simply by way ofMovieClip.play(). No need for theSound.positionproperty, because noSoundinstance is necessary. (Again, the only case for aSoundinstance with timeline audio is to adjust its volume or panning dynamically.) Stream audio restarts from where it left off by definition, because it’s synchronized with its timeline.If you use a
Soundinstance for more than what I’ve described — that is, to actually load external MP3 files or attach audio assets from your Library — then you’ll use theSound.stop()andSound.start()methods (along with theSound.positionproperty) to resume sound. In this case, audio will not be attached to a timeline frame at all, and you’ll need to use bothMovieClipandSoundmethods to match up the halting/re-starting of your timeline animation with your audio.That’s another hint that you’re using timeline audio, because the
play()andstop()functions correspond to theMovieClip.play()andMovieClip.stop()methods. In other words, your code is only controlling a timeline, and theSoundclass doesn’t seem to be involved at all.As long as that timeline code is set to Stream, yes.
It’s hard for me to pinpoint what’s going on, but it might be that your main timeline (or a parent of the movie clip in question) is still moving forward, which updates the screen toward the following movie clip.
That’s really one of those “an art and a science” issues. It often takes a bit of fiddling to get your compression right. You’ll see configurations for both Event sounds and Stream sounds in the Publish Settings dialog.
More importantly, though, you need to fully digest the distinction between timeline audio and programmatic audio (the
Soundclass).In one of your questions/comments, you were wondering where to put all your code. The answer to that, ultimately, depends on what works best for your workflow. It’s generally possible to put all of your code — all of it! — in frame 1 of your parent-most timeline. But wherever code does appear, it simply needs to know what objects to reference (where those objects are, in other words). The easiest way to help Flash help you is to provide instance names for objects, such as movie clips, that are created by hand. This way, your code can reference objects by name and invoke the relevant class methods (or properties, or events) on them.
June 12th, 2008 at 1:10 pm
Thanks for your help, David - it’s a lot for me to digest just now, as I find this all so confusing. I don’t know a sound object from a sound class, if that statement is even correct!
Each movie clip contains several layers, including actions, audio, and several layers for animations. The audio is actually placed along its own layer, and is currently set to stream in the properties dialog.
At present I can pause the first movie clip in the timeline along with it’s audio - however, after the apt amount of time elapses (i.e. the first clip is 8.3 seconds at 29fps, 271 frames in length), the next clip plays.
June 12th, 2008 at 1:24 pm
Kelley,
These concepts are difficult, for sure, until they sink in. Chin up!
In ActionScript, everything is considered an object, and objects are defined by their individual blueprints, which are called classes. Your movie clip symbols, for example, are instances of (aka “objects of”) the
MovieClipclass. As you already know, movie clip symbols have certain characteristics, such as width and height, position on the stage, number of frames, etc. These correspond to properties of theMovieClipclass; in AS2, those are_width,_height,_x,_y,_totalframes, and so on. Movie clips can also do things, such as go to a frame and start playing. Such doing-things features are called methods (gotoAndPlay(),loadMovie(), etc.). Movie clips can also respond to things, such as a mouse click. Those features are called events (onPress,onRelease, and so on).And it doesn’t stop with movie clips. Everything is an object, and all objects are defined by classes. Text fields are defined by the
TextFieldclass, whose properties govern things like width, height, number of characters in the text field, and more; whose methods govern the things a text field can do (setTextFormat(),getFontList(), etc.); whose events govern the things a text field can respond to (onChanged,onSetFocus…).Button symbols are defined by the
Buttonclass. Arrays are defined by theArrayclass. Blurs are defined by theBlurFilterclass, dates by theDateclass, sounds by theSoundclass, and on and on. Not all classes feature properties, methods, and events, but those are the main three categories to look for when consulting the ActionScript Language Reference.In your case, you’re dealing with audio attached directly to keyframes, which means you’re not using the
Soundclass, which is fine. Because of that, however, you can’t make use of any of theSoundclass members (no properties, methods, or events) — except as those relate to theMovieClipclass. Why? Well, theMovieClipclass comes into play because your audio is attached to keyframes, and keyframes are stored in a timeline. All timelines, including the main timeline, are instances of (aka objects of) theMovieClipclass. This is what allows you to optionally adjust a movie clip’s volume and panning by way of theSoundclass (see “Understanding the Sound Constructor (AS2)“), but nothing more.That means something is telling the next clip to play. Perhaps there’s code in the last keyframe of your current movie clip that tells the next one to move?
July 7th, 2008 at 8:22 am
Hi David
Quick question re the above. I have a series of .swf movies that load in to a master movie clip. Each child .swf file has a series of mc’s that contain a timeline with embedded audio and animations synced with the audio.
Your code works great if I place the control panel that pauses/plays the audio within each child .swf. However, I want to be able to send commands to the pause/play buttons that reside within the master timeline but I am really struggling getting it to work once they have been loaded in to the main timeline.
I have tried targetting the pause/play buttons, but nothing seems to be working. Do you have any ideas why this is happening, or can you not use this method.
I am basically passing a command from the child timeline to the main timeline, to perform an action in the child timeline. I am just not sure with the attachSound method etc.
Thanks in advance
October 16th, 2008 at 7:24 pm
This is the first reply in a while, but I just have to reiterate the very first reply to this thread and, no doubt, others after that (I haven’t read them all). I couldn’t agree more mStudios’ sentiments, in regards to the no-bullsh!t approach, to this handy little tutorial. I’ve been searching around, trying to resolve a similar issue and it’s refreshing to finally find somebody who speaks my language!
Thanks David!
October 28th, 2008 at 5:04 am
Hi David
Im using AS3 at the moment and building an interactive music video for my assignment … basically we have keyed out video footage of the band and each member is its own MovieClip that is embedded into the main Timeline
they reside at the very top level of layers. Underneath these layers we have the interactive objects and background scene. I have set up the navigation so that when you arrow key to the left or right it will “switch scenes” - basically going from one background scene on one frame to another scene on another frame ….
in order to syncronise the lead singers vocals with the song I had to embed the audio file as a layer within the lead singer movieclip - i did try to call the mp3 file to play by code but the audio & video never synced correctly
my problem is this : i have 5 scenes that you can move around on …. scene1 sits on frame 1, scene 2 on frame 2, etc … when you get to scene 5 the next click event will take you backwards on the timeline to scene 1 … as soon as this happens though the song within the vocals_mc layer seems to restart playing and it creates this layered double-sound effect … if i continue navigating or going backwards, the song layers again and again so that i have this annoying cacophany of copies of the same song playing simultaneously
what is the quickest, easiest way to avoid this without having to sacrifice the syncronised video/audio?
many thanks in advance for any help you can provide. This is easily the best explanation of AS2 sound I have seen yet so thank you!
October 29th, 2008 at 8:51 am
To AndyD …
Your goal is definitely doable, and it all comes down to finding the right object reference(s), like traversing folders on your hard drive. I should say, your goal is doable if it’s what I think you’re asking — but this part throws me a bit:
What command are you passing from the child to the parent? Where the the actual pause and play buttons located? It sounds like your pause/play buttons are located in the main SWF (the parent SWF). If so, those buttons can send messages to the loaded (child) SWFs, instructing them to stop and resume their audio. If the
attachSound()code resides in the child, your object reference would be whatever object points to the loaded SWF, and then whatever variable name you gave the child’sSoundinstance, all separated by dotsparent.child.mySound).If you can explain the reason for traveling the opposite way — from child to parent — I’ll try to help you figure out the pathing. In principle, though, you should be able to path to the parent by invoking the
MovieClip._parentproperty in the main timeline of the child as the beginning of your object reference.To Jordan …
Glad to hear that, man! I appreciate the comment!
To Lele …
There’s nothing wrong with that, but make sure you set the audio’s Sync option to Stream in the Property inspector.
That definitely sounds like your audio is set to Event in the keyframe that introduces the audio. Try Stream, which locks your audio in-step with the visuals, and in addition, allows you to stop that timeline with
MovieClip.stop()(and restart it again, of course, withMovieClip.play()). That’s the benefit of the Stream setting for Sync. The benefit of the Event setting is that the audio loads fully into memory first, before playing, which allows it to play independently of the timeline. There are pros and cons to everything, and in the case of Event — this is my hunch, mind you — you’re hearing those loops. If you’re using Event, by the way, don’t count on it that the audio will sync to the visuals on everyone’s computer. When you use Stream, you can rely on it.