How to Toggle Sound Globally (AS2)
Flash is a great medium for presenting sound, whether narration, music, or basic UI clicks and whirs. That said, it’s a good idea to provide a way for people to toggle sound off, if they prefer silence. You may have heard or read about the global stopAllSounds() function. It’s good in a pinch, because it does exactly what its name implies: any sound currently playing is abruptly shut off. Of course, additional audio in subsequent frames continues to be heard. If other buttons are wired to produce sound, they continue to do so when clicked. stopAllSounds() isn’t a toggle, it’s just an immediate silencer.
This topic comes up a lot in the forums, actually. You may have heard about using the Sound class to trigger sounds with ActionScript. It’s possible in this way to check against a single, globally accessible Boolean variable before invoking Sound.start(). Naturally, this means that every last sound in your SWF would have to be programmed, which may be a daunting prospect. Personally, I’m a fan of the Sound class. It’s great for games and ActionScript-based presentations, but there’s certainly something to be said for the drag-and-drop utility of placing sound assets by hand in a timeline. So … is there an easy way to toggle these sounds (any sounds) off — and then on again? You betcha.
An answer, short and sweet
Add the following to frame 1 of your scripts layer.
var globalVolume:Sound = new Sound();
I know, pretty short, right? This allows you to adjust the volume of the whole SWF from two buttons. Assuming the instance names btnSoundOff and btnSoundOn …
btnSoundOff.onRelease = function():Void {
globalVolume.setVolume(0);
}
btnSoundOn.onRelease = function():Void {
globalVolume.setVolume(100);
}
How it works
A variable is declared with the arbitrary name globalVolume. This points to an instance of the Sound class, so the declaration includes the :Sound suffix. The Sound instance is generated by the constructor new Sound(), which is built to accept an optional parameter (a reference to a movie clip) — but since it’s optional, we’re leaving it out. Why? When the parameter is omitted, the Sound instance governs audio across the whole SWF.
The buttons simply invoke the Sound.setVolume() method on our globalVolume instance. Enter 0 to silence the SWF and 100 to unsilence it.
Variation
Two buttons are fine, but often enough, you see a single button that handles the whole procedure. Let’s see how to accomplish that. All we need is a Boolean to keep track of what state we’re in: volume on or off.
var volumeOn:Boolean = true;
var globalVolume:Sound = new Sound();
btnSoundOff.onRelease = function():Void {
if (volumeOn) {
globalVolume.setVolume(0);
} else {
globalVolume.setVolume(100);
}
volumeOn = !volumeOn;
}
The if statement could be written like this …
if (volumeOn == true) { … };
… but the shorter version makes just as much sense: all an if statement does is evaluate an expression to decide if the result is true or false — which are precisely the two values volumeOn returns.
Note that if volumeOn returns true, globalVolume.setVolume() is set to 0 and vice versa, but in all cases, the value of volumeOn is set to its own opposite. The logical NOT operator (!) handles that part (volumeOn equals not-volumeOn; in other words, whatever volumeOn isn’t).
May 12th, 2006 at 10:23 pm
I don’t think people really pay much attention to the optional target parameter. A lot of the time, people have multiple sound objects using new
Sound(). And then they try to change the volume of one and the rest of them change!Here’s another way to write the toggle button:
May 13th, 2006 at 2:25 pm
NSurveyor,
That’s very cool! Done that way, you don’t even need the
volumeOnvariable I used in my example.Here’s how this one works, starting from the inside out.
Sound.getVolume()returns the value of aSoundinstance’s current volume. By default, volume is 100, so the first time this button is clicked, the value ofglobalVolume.getVolume()is 100.This number is added to 100, which makes 200. This sum (inside parentheses) is evaluated against the number 200 by way of the modulo operator (
%); in other words, the expression now under evaluation is 200 % 200. Modulo calculates the remainder of one number is divided by another. In this case, 200 is divided by 200, which leaves a remainder of 0. Therefore,globalVolume.setVolume()is fed the parameter 0, which silences the audio.The next time this button is clicked,
globalVolume()returns 0, which is added to 100. This sum is divided by 200, which leaves a remainder of — well, wait a minute! 100 / 200 is 0.5. There is no remainder, but the division does not resolve to an integer. In ActionScript, it looks as if any number modulo a number higher than itself equals the number it was before the operation. So, hereglobalVolume.setVolume()is once again set to 100.Pretty slick programming!
May 13th, 2006 at 3:14 pm
Thanks… and if you think about it… 100/200 = 0 R100.
The a%b = a when a is less than b is not always true… (well, because of negatives)
(-3) % ( 2) = -1
(-3) % (-2) = -1
(-3) % ( 4) = -3
(-3) % (-4) = -3
The sign of a%b matches the sign of a.
And of course, when b=0, you get NaN…
alert(”uhoh”)
May 13th, 2006 at 3:32 pm
And here’s an easier way… should’ve thought of this earlier
When the volume is 0, it becomes 100-0 or 100, and when the volume is 100, it becomes 100-100 or 0.
May 14th, 2006 at 6:30 pm
There are a million ways of writing this!
May 15th, 2006 at 8:21 am
Yup, makes perfect sense.
These are creative solutions, NSurveyor. What I like about these is that you’re using the resources given — namely,
Sound.getVolume()and a variety of operators — and using them succinctly to accomplish a goal.June 6th, 2006 at 10:38 pm
Here’s another one:
June 18th, 2006 at 4:31 pm
Hi David,
Is there any way I could put all of that script into the buttons themselves? I’ve tried a bajillion varients on the code above, and I can’t seem to get it to recognize my instances. Is there anyplace i can find a fla example of this?
Thanks!
Conan
June 18th, 2006 at 5:55 pm
Conan,
You certainly could put the button code directly on your buttons — and I’ll show you how to do that — but the instance name approach is a fundamental skill. To my thinking, you should do what it takes to understand how that works. Fortunately, there’s nothing to it, in this case. It all comes down to paths. If your ActionScript is in the main timeline and your button is, too, then you simply need to reference the button’s instance name. If the button is nested inside a movie clip, you must reference the movie clip’s instance name first as part of your path, and then the button’s instane name. My hunch is that your paths are wrong, somehow.
Since you asked, here’s the other way to do it — the older way. Keep in mind, the
on()event handler is a Flash 5-era mechanism. It still works, but it’s not on the list of current best practices.As before, instantiate the
Soundclass first, in a frame of the main timeline.Then, on each of your buttons …
September 19th, 2006 at 5:27 am
I’ve placed a sound clip on the OVER frame of a button, (inside the button). So when ever the mouse goes over it plays. Likewise im planning to have different clips played here and there.
I tried your code but it just doesn’t seems to solve the problem. It stops the background music but when ever i go above the buttons it sounds.
May its not effecting the upper level, please help me.
September 19th, 2006 at 7:18 am
Uchitha,
Wow, good find! I’m surprised at Flash, but you’re absolutely right: button timeline sounds seem to be immune to global volume settings. Here’s how you can work around it.
Note the Boolean variable,
volumeOn, in the Variation above. You can use that same variable to give your buttons a way to check if they should play or not. Keep using the originalSoundinstance to control your global volume, and instantiate a secondSoundobject to hold your button sound effects. You could use the variable namesfxfor that. Make sure each button has an instance name (say,button1).Those three Button events represent their corresponding button symbol frames. You can use that same
sfxvariable for all your buttons. Each time, you’re simply invoking theSound.attachSound()method, to attach a sound from your Library, then theSound.start()method to play the attached sound.Make sure you set a Linkage id for each sound in the Library you intend to trigger in this way.
One last step. Remember that Boolean variable? Assuming you’ve used the Variation above the
volumeOnvariable will either betrueorfalsedepending on the global volume setting. Use anifstatement in your button event handlers to test whether or not to play …September 23rd, 2006 at 5:36 am
Thanks
for help, it works now !
September 23rd, 2006 at 8:51 pm
Glad to help, Uchitha.
December 14th, 2006 at 6:10 pm
This saved my life. I’ve been looking for a mute function that works all day. This is SO easy and quick! Just wanted to thank you!
KC
January 10th, 2007 at 3:05 am
Great post,
thx
VD
January 19th, 2007 at 5:17 pm
I’ve been looking for this, but in slider form. Thoughts?
January 19th, 2007 at 6:45 pm
mike,
A slider suggests more of a gradual change to me than a toggle. But either way, if you want to adjust the volume for your whole movie, the key is simply to instantiate a
You could have your slider set the
Soundinstance, as above, without the optional target parameter — see details in “Understanding the Sound Contructor.” The instance name (the variable’s name) doesn’t make any difference, but I like to give variables descriptive names, andglobalVolumefits the bill.Sound.setVolume()method to any number between zero and 100, and as long as your Sound instance applies to the whole move — thanks to the absent constructor parameter — you’re good.March 17th, 2007 at 9:08 am
Just wanted to thank you for a great post! Been using this for several projects of mine. However, I just encountered a little problem.
When loading external swf’s into my main movie clip the sound toggler doesn’t quite work as intended. It can turn the sound off for the current swf, it can turn it on if it was muted from start. BUT if turning off the sound on the particular page, it wont start play again if i turn it on, unless I reload my page. Any solutions for this? (if i manage to make myself understood here ^^)
Also I was checking around YouTube at the same time i was looking at my website and toogled the sound off on my site, and the sound of the YouTube movie, in another firefox tab also stopped playing o.O
March 17th, 2007 at 1:02 pm
Mikaela,
I’m not sure I fully understand your issue, but I’ll try to reply.
The ActionScript I showed adjusts the volume for the whole movie (that is, a SWF). It doesn’t pause or restart sounds. Those continue playing (or not) on their own, as if nothing had happened. The volume control is very much like temporarily turning off your speakers. If your loaded SWFs contain sounds triggered by a keyframe (just for example) and you turn down the volume in the main SWF, that keyframe in the loaded SWF may pass. When you turn up the volume again, that passed sound will only occur again if its triggering keyframe is visited a second time by the playhead. Does that make sense?
I’m curious about your YouTube experience, for sure. As far as I know, the ActionScript I showed shouldn’t affect the volume of SWFs on another page.
March 17th, 2007 at 11:40 pm
Yea, I know that it works as if you turn down the volume of your speakers but i kind of hope there was a way around this, but what you describes makes fully sense so i guess there isnt
Yea, i was pretty surprised myself. And plus it didnt only stop the sound - it also paused the movie playing in YouTube :S
April 17th, 2007 at 1:33 am
Thanks dude… I’ve spent like 2 hours trying to figure this out. You’re my savior. Great tutorial!
April 17th, 2007 at 10:03 pm
Kyle,
Rock on!
April 17th, 2007 at 10:28 pm
Thank you so much!!! I’ve been hunting for hours trying to find something with these results.
I added a fade to mine. Works great. Thanks.
April 17th, 2007 at 11:01 pm
Jeremy,
Glad to hear it!
April 20th, 2007 at 4:22 am
I only found this after I created a whole sound manager system. Although the manager does allow sounds to be paused (they fade out to a pause) and started up again from the last point as well as a bunch of other functions like force starting sounds (cos of flash bugging out in complicated sites). But I really wish I’d seen this post first. Woulda negated me having to fade out each sound individually.
Nice code-wars on the toggle button:)
April 23rd, 2007 at 12:09 pm
Hey two questions:
–You guys are talking about fading the sound, that sounds awesome, how do you do that?
–When I’ve used this I’ve created a movieclip with frames showing on and off, and I’ve had the AS toggle between them. Would there be a way make a parameter to tell it that if the volume=100 to show the onframe and vice versa?
April 23rd, 2007 at 10:32 pm
Casey,
To fade sounds, you update your volume over time. You could use, say, a
MovieClip.onEnterFramehandler orsetInterval()to invokeSound.setVolume()repeatedly on an instance and increment/decrement the value until you hit the desired volume. For example, this would fade in an existing instance,s, from zero to one hundred, counting by fives:As for showing one keyframe or another — I assume these keyframes are part of a movie clip “button,” right? — just invoke the
Sound.getVolume()method to determine the volume. If this button has anonReleasehandler, and contains frame labels “toggle off” and “toggle” on, with aSoundinstance nameds…April 24th, 2007 at 4:25 pm
Cool.
I’m not sure what I’m doing wrong on the sound fade. I’m using the global volume paramater for S, is that big no no?
April 25th, 2007 at 10:05 am
Hey just wanted to say thanks for the great work above to everyone else that contributed via comments, but mostly to David as you saved me a lot of potential baldness!
Be Exellent to each other!
April 25th, 2007 at 11:57 pm
To Casey …
Not sure what you mean by “global volume” parameter. In the above sample code, the letter “s” represents a
Soundinstance; that is, it’s a variable,s, declared earlier — not shown in the my reply sample code. A more complete sample might be …To Alan Fair …
Party on!
April 26th, 2007 at 11:55 pm
Thanks David!
I got everything to work! If folks like you don’t understand, while many of us are learning a full understanding of AS you folks help us understand and acheive goals big and small and we appreciate it.
Thanks again.
April 29th, 2007 at 8:27 am
Hi David,
I have a movie in which there are several movie clip symbols containing sound and visuals. I move from obe clip to the next by loading the appropriate movies into the main timeline using the attach method –
this.target_mc.attachMovie(mcName, “target_mc2″, 0)
I have tried a variety of ways to try to control the volume using the methods you described above without success. I can control the volume if the sound and visuals reside on the main timeline but this creates a host of other problems. Is there a method by which the volume for embedded movie clisp can be controlled?
May 1st, 2007 at 3:09 am
Chris,
Once the Library clip is attached, it becomes available to ActionScript via its instance name. Rather than constructing a
Soundinstance associated with the whole movie, as shown in the original article, you could construct yourSoundinstance and pass in, as a parameter, the instance name of the newly attached movie clip. That will associate theSoundobject with that clip, controlling its audio.May 7th, 2007 at 12:00 pm
Hi,
I’ve found your posts on using sound in Flash extremely helpful. I am struggling with a challenge that I’m sure is a pretty common procedure.
I have created a global sound object, to which I am attaching various sound files throughtout a Flash presentation. Essentially, there is a sound file associated with a scene. Within the scene I want to sync simple animations (image fades from one to another) with specific points in the sound file. I understand the theory of the position property, but I am having trouble making it useful in a script that will basically state:
When the sound reaches a position of 5 seconds, advance the playhead.
I have a global variable named “narration” which is where my Sound object lives.
I use the following statement on an earlier frame:
narration.attachSound(”01-01″);
narration.start(0,0);
The sound begins playing.
I want to stop the playhead at a subsequent frame, and place a command that only advances the playhead when the sound’s position reaches a certain point.
I’ve tried something like this:
stop();
if (narration.position/1000 == 5) {
play();
}
I need a function or command that I can reuse several times per sound file.
Any guidance you can provide would be fantastic.
May 13th, 2007 at 8:10 pm
Chris,
My first inclination, here, is to send you to my cue points article on Adobe.com. The article walks you through a way to associate cue points with MP3 files in both ActionScript 2.0 and 3.0. My editor recently asked me to update that article, because I originally wrote it for the public alpha version of Flash, which is no longer available. If you’re coding in AS2, it won’t matter; if you’re coding in AS3, you can probably still get all you need out of the article, but I do plan to update it as soon as I find a moment.
June 7th, 2007 at 1:47 pm
A method to fade the sound:
var globalVolume:Sound = new Sound();
function globalMusicVol(target:Number):Void {
var temp:Number = new Number(globalVolume.getVolume());
this.createEmptyMovieClip(”fader”, this.getNextHighestDepth());
fader.onEnterFrame = function() {
if (target>temp) {
temp += Math.ceil((target-temp)/10);
} else {
temp += Math.floor((target-temp)/10);
}
globalVolume.setVolume(temp);
trace(temp);
if (temp == target) {
delete this.onEnterFrame;
}
};
}
Then simply call the function and the target sound on the button, for example:
globalMusicVol(100)
… to make it become full volume.
June 7th, 2007 at 7:41 pm
Ryan,
Thanks for the input!
I use a technique similar to this myself. The only thing I would suggest is to omit the re-instantiation of
fadereach time the function is called (no need to create a new movie clip object every time, especially if it’s only being used for itsonEnterFrameevent) — or do away with the new extra movie clip altogether by looping onsetInterval().July 3rd, 2007 at 8:32 pm
very nice comments from both the editor and Ryan…creating a movieclip containing in second frame the loop and fading in/out with ryan’s script from the main timeline helped me solve the problem i had with sound looping gaps between loops by using the edit envelope for the sound in second frame….
thx guys….helped a lot here.!….
July 5th, 2007 at 12:37 am
cafeine,
Glad to hear it!
July 5th, 2007 at 3:16 am
I’m trying to fade down/mute the background music sound when playing the flv using the Netstream object, so the FLV file audio is the only one being heard. When pausing the audio or getting out of the video page.. background music sound is fade up/unmute.
In shortwords, separating the background music with the Video music, so either or sound is heard. Not both
Thanks..
July 5th, 2007 at 7:18 am
TicoXX,
To control sound for individual objects in ActionScript 2.0, you’ll need a separate movie clip for each source of sound. For video, in particular, you’ll want to read “How to Adjust the Audio Portion of Flash Video.”
July 16th, 2007 at 9:33 am
Hi there.
Is there anyway to make a global volume SLIDER?
For instance, I have a slideshow, of 100 slides.
I would like the user to be able to adjust one slider once and have it affect the volume of all slides.
thanks!
July 16th, 2007 at 1:19 pm
Mike,
Sure thing. A slider would operate along the same lines as as the progress bar/scrubber described here: produce two movie clips (a knob and a track), and note the ratio of the knob’s distance across the track. Use that ratio to determine a number between 0 and 100 to use as the
Sound.setVolume()method’s parameter. I’ll do up a blog entry on this topic.July 25th, 2007 at 10:57 am
Mike,
Quick update: the slider blog entry is here. kweku asked for pretty much the same thing, and I had forgotten you were also interested. In your case, you won’t need the video portion mentioned at the bottom, but it should be pretty easy to see how you can modify it for a
Soundinstance.August 5th, 2007 at 3:57 pm
Hello everyone. This is going to sound a little naive, but how do I start a .SWF file with the sound off, then when I hit play, the sound plays from that point in the .SWF
Thank you so much!
August 5th, 2007 at 7:01 pm
Rick,
Check out “How to Pause Sound and Resume Where it Left Off.”
August 5th, 2007 at 8:23 pm
David,
Thanks for that. However, how do i start with the sound off? I only want the sound to play when the viewer clicks the sound button. However, I want the movie to continue playing and the viewer can watch the movie. The sound picks up in the correct spot so that it matches the video.
August 5th, 2007 at 8:47 pm
Rick,
If you’re using the trick above to silence the whole SWF at once, then you’ll set your
globalVolume’s volume to 0 before starting any other sounds. At that point, start your other audio (or FLV video, or whatever) and when the sound picks up — because, say, the user clicks a button — set theglobalVolume’s volume to 100. The audio will match the video (or your timeline, or whatever) because those other sounds will have been playing all along — it’s just that your “global volume knob” will have been turned down. Make sense?August 5th, 2007 at 11:27 pm
David
I must be doing something wrong. I’ve got three layers.
1 layer is sound file;
2 layer has this code in frame 1:
var globalVolume:Sound = new Sound();
August 6th, 2007 at 7:06 am
Rick,
In a script layer in frame 1, use this:
Now your movie is prepped, and the “global volume knob” has been turned all the way down. As your timeline progresses — or as you otherwise start new sound (e.g. other
Soundinstances) — use this …… to turn up the global volume.
August 13th, 2007 at 11:17 am
Hi, would like to reply an old post here
on 17 march 2007 Mikaela wrote
“…Yea, i was pretty surprised myself. And plus it didnt only stop the sound - it also paused the movie playing in YouTube :S”
This problem hits so many Flash developers. The solution we found here is, if you create a sound object like
my_sound = new Sound();
my_sound.attachSound(”bg_music”);
and you want to stop it without causing problem to your flv and other sound object, you have to do it the following way
my_sound.stop(”bg_music”); //This one works
my_sound.stop(); //This one stops everything, including flv
Hope this help
Regards,
GC
September 2nd, 2007 at 2:06 am
hi!
is there a way to toggle sound using your keyboard (for example, the s key) instead of using a button? it would be fantastic if someone could help with this! thanks
September 3rd, 2007 at 9:42 am
To GaryC …
I may have misunderstood Mikaela’s question, but I thought the issue in that post was that Mikaela’s code seemed to stop not only the audio in the desired SWF, but also in a completely different SWF in a separate Web page (a YouTube video). That’s what struck me as odd. Your comment about the optional parameter in Sound.stop() is helpful, in any case. Thanks!
To varty …
Sure thing. In order to accomplish that, you’ll handle the
Key.onKeyUpevent, rather than theButton.onReleaseorMovieClip.onReleaseevents. The syntax is a bit more wordy, but here’s a quick example:In the above, the letters p (“play”) and s (“stop”) cause the volume to be set to 100 or 0, respectively. In this case, you need an “ambassador”
Objectinstance to act as your liaison, instead of assigning the function directly to a button object. That kind of makes sense here, because keystrokes aren’t really tangible objects like button or movie clip symbols.The
listenerobject, then, stands in for theKeyclass and has a function assigned to itsonKeyUpproperty. When a key is lifted (after it has been pressed), a series ofifstatements test to see which key was the last to be pressed; this is afforded by the staticKey.getCode()method. The numbers 80 and 83 correspond to “p” and “s” (search “Keyboard Keys and Key Code Values” in the Help docs to see the full list).September 11th, 2007 at 10:00 am
How would I automatically mute the sound when the animation gets to a certain keyframe and then when it exits that keyframe i would like it to unmute and continue playing
(this is for a site that has background music and on 1 page it has a video where i want to stop the background music until they go to the next page where the background music will start up again
September 15th, 2007 at 7:18 pm
Hardik,
For something like that, rather than invoke the
Sound.setVolume()method in response to button clicks, you’ll want to invoke that method from a keyframe. In frame one, for example, put this:var globalVolume:Sound = new Sound();Then in frame 250 (or whatever) reference that
globalVolumeobject and call itssetVolumemethod:globalVolume.setVolume(0);At a yet later frame (500, say), add another keyframe to your scripts layer and turn the volume back up:
globalVolume.setVolume(100);But keep in mind: the technique shown in the original blog entry is a for setting volume globally. If you want to adjust the volume of the background music only, you’ll have to associate that Sound object with a unique timeline, because in ActionScript 2.0, timelines (movie clips) are effectively your sound channels. See “Understanding the Sound Constructor.”
October 8th, 2007 at 10:20 am
Ok.. this rocks!
Tnx David and all that camed with different solutions…
but i have a question.. i use these code for a banner. and the first time it plays evrething works incredible fine.. but when it plays again i can’t hear the music anymore
Any solutions pls.. these will help me right now…
Thx
October 8th, 2007 at 10:25 am
neah.. nevermind.. it was a silly thing.. i solve it…
)
so complety easy.. just a loop
tnx anyway
October 8th, 2007 at 2:07 pm
luce,
Glad you found the fix, and glad you liked the tutorial!
October 10th, 2007 at 11:38 am
Hi I use your script without any problem, the only problem I think so its when y play a FLV with the basic controller of flash 8 o 9 they mute too it’s correct this or maybe is something rong i did, the music it’s a mp3 file in the timeline with the option stream and loop. Thanks in advance.
October 10th, 2007 at 12:06 pm
rick,
The ActionScript suggested in the original article describes a way to toggle a SWF’s sound globally. Effectively, it allows you to “turn down the volume knob” on the whole movie, which would indeed mute any FLV content in that same SWF. If you want to toggle the MP3 itself, make sure to associate your
Soundconstructor with a timeline (a movie clip) that isn’t the main timeline. You can read more about this distinction in “Understanding the Sound Constructor.”October 23rd, 2007 at 2:35 pm
Had a question regarding a specific project I’m trying to get some global sounds for. Essentially it’s 24 diff movies w/in a navigation system. There is a prev-play/pause-next set of buttons that will do what they say (like a dvd player).
I’m trying to get a global audio mute button to work and am not sure if the code suggestions above will apply to this situation. See each of these movies (1-24) have their own narration audio files embedded in the timeline.
There are also some audio controls associated with the prev-play/pause-next buttons:
PREVIOUS BUTTON:
on (release) {
stopAllSounds();
this._parent.prevFrame();
}
PLAY BUTTON:
on (release) {
//navigationStop();
//stopAllClips();
stopAllMovies(_root);
}
NEXT BUTTON:
on (release) {
stopAllSounds();
this._parent.nextFrame();
}
What do you guru’s suggest? I can of course supply more info if needed.
Project is here:
http://granza.flyinghstudios.com/Granza_Working_R4_loader.html
Thanks!
October 23rd, 2007 at 3:28 pm
Andy,
The code outlined in the article should have you covered.
It’s like a volume control on your main amp. Doesn’t matter how many instruments or microphones are plugged into it: when the main volume is turned down (or turned off), nothing is heard.
I’m not sure what your
stopAllMovies()function does … that’s got to be a custom function, because there isn’t a nativestopAllMovies()function or method in ActionScript. But I’m guessing that’s already taken care of?October 23rd, 2007 at 4:41 pm
Nevermind! Got it taken care of. Many thanks gents!
October 23rd, 2007 at 7:00 pm
Thanks David. How’d you know I was a musician…more specifically a guitarist?
Your amp analogy makes perfect sense. I ended up getting it all squared away in the end. Feel free to delete the long entry I had.
October 23rd, 2007 at 8:16 pm
Andy,
Haha … lucky guess about the musician metaphor! I just bought a small amp myself for my new Moog theremin. Funny coincidence. Glad you solved it.
October 31st, 2007 at 9:07 pm
Just a quick note to say THANK YOU!!! I had been looking for 3-4 hours for a way to turn global sound on or off. You made my day!!!
November 1st, 2007 at 2:26 pm
john,
You’re welcome!
December 21st, 2007 at 12:46 pm
Hi everyone -
I’ve run into a roadblock and I’m hoping you can help.
My problem concerns: scoping variables across levels to start() playing sounds and setVolume().
Situation: I’m trying to use Dave Stiller’s solution to Uchitha’s problem back on September 19th, 2006 at 7:18 am. It worked great when the movie was standalone. But now that I’m using a loadMovieNum to place that file on _level2 - my buttons are no longer playing sounds.
PREVIOUS SOLUTION FOR UCHITHA:
// Instantiate Sound for sfx
var sfx:Sound = new Sound();
// Handle Button events
button1.onRollOver = function() {
sfx.attachSound(”UP-sound”);
sfx.start();
}
This did work - until I loaded the movie onto _level2. The buttons then stopped playing sounds all together.
*I have tried scoping the buttons back to _level2…. but no sound.
button1.onRollOver = function() {
_level2._root.sfx.attachSound(”UP-sound”);
_level2._root.sfx.start();
}
Any help would be greatly appreciated!
Very best!
Andy
December 21st, 2007 at 1:05 pm
Andy,
The success of your scoping is going to depend on where each of these objects resides. If you’re instantiating
Soundin the same SWF that gets loaded into_level2of another SWF, then it looks to me as if yourSoundinstance (sfx) is in the root of_level2, along with your buttons. The buttons should be smart enough to findsfxas shown in your first snippet.In AS2, the reference to
sfxinside your function will look insidebutton1first, hoping for a property namedsfx. When it doesn’t find that, it will step up to the object that containsbutton1and look there (where it should findsfxjust fine). If that’s not working, that baffles me a bit, but you could certainly try an explicit reference like this:In any case, the expression
_level2._rootisn’t a valid one, because_rootis the base of_level2from the point of view of_level2(in AS2, levels are a bit like multiple copies of a Word document open in Word: they’re all related, but each is its own document).December 21st, 2007 at 2:28 pm
Hi David - thank you so much for the super fast reply!
Here’s where I’m at…. I tried your suggestion to explicitly reference ’sfx’ and it is working as a standalone file. But when loaded into _level2, I’m still getting no sound. I’ve pasted my code below. All buttons and code are on the main timeline of that movie.
var sfx:Sound = new Sound();
sfxbtn1int.onRollOver = function():Void {
this._parent.sfx.attachSound(”low”);
this._parent.sfx.start();
}
sfxbtn1int.onPress = function():Void {
this._parent.sfx.attachSound(”high”);
this._parent.sfx.start();
}
The button is named ’sfxbtn1int’ and sits right on the main timeline of the same .swf.
Any other ideas? I’m really at a loss right now. I made sure that there was no conflicting code or instance names in my _level0 movie before writing you back.
Thank you again for helping me work this out!
Andy
*sidebar: The reason I’m doing all of this is because setVolume isn’t working on my buttons with timeline sounds (which is how I came across his page). Just trying to get a simple mute button working.
December 26th, 2007 at 10:51 am
Hi David,
The code in this tutorial doesn’t seem to work with ActionScript 3.0. I get an error: “1120: Access of undefined property globalSound.
December 27th, 2007 at 6:54 pm
Brian,
Hey, thanks for bringing this up! I wrote this tutorial in May, 2006, before ActionScript 3.0 was officially available for Flash. The above sample code is indeed ActionScript 2.0, so you’re right — it won’t work in an AS3 document. (It does happen to work in AS1, provided you drop the post-colon suffixes [
:Soundand:Void]).Time keeps marching on, so I’ve updated the title of this article to reflect its basis in AS2.
Sound is handled quite differently in AS3, and I’ve been planning to update this how-to along with a number of the others that are often consulted. In the meantime, check out the
SoundTransformandSoundMixerclasses in AS3: those are the ones you need to change volume globally.In the above,
xfis an arbitrarily named variable set to an instance of theSoundTransformclass. Rather than the usual expressionnew SoundTransform(), this one gets its instance from the staticSoundMixer.soundTransformproperty. TheSoundTransforminstance (xf), has avolumeproperty, which is set to 0. TheSoundMixer.soundTransformproperty is then set back to the updated value ofxf. In AS3, a full volume is indicated by 1 rather than 100 (the range is 0 to 1 in AS3, so 50% volume is 0.5).December 30th, 2007 at 8:23 pm
[Follow up on Andy …]
Since his post on Dec 21, 2007, Andy shared a few of his files with me at my request. We determined that his object references were all correct. Oddly (and very interestingly), the
Soundclass simply doesn’t seem to work — in the context of Andy’s project — when the SWF that contains the code is loaded into another level.By using
MovieClip.loadMovie()(instead of the oldloadMovieNum()function), I was able to view Andy’s file as he expected and recommended that workaround.January 11th, 2008 at 9:53 pm
Hello David
I am very new to ActionScript and I am trying to learn 3.0. That said, I have two concerns. First, I am building a site where I simply want a soundtrack to loop in the background at the start of the movie and I would like to use a single button so the user can toggle the soundtrack on or off. I am at a loss because I do not want it to be a global function that will affect other rollover sounds, for instance.
Second, where has the mailto ability gone? I am using this bit of script below to open an email window but it also opens a blank browser window!
function gotoLimnerMail(evt:Event):void {
var limnerUrl:URLRequest = new URLRequest(”mailto:limnerian@mac.com”);
navigateToURL(limnerUrl);
}
bConfabulate01.addEventListener(MouseEvent.CLICK, gotoLimnerMail);
Can you please give me a nudge?
At your convenience!
Thank you,
Fritz
January 21st, 2008 at 9:31 am
Fritz,
Your syntax is just fine for the
mailtoendeavor. I tested very similar code on my own machine, and the only thing that opens is a new message window for my email client. Have you tested this in a SWF that is a) embedded in an HTML page and b) located on a server? You may encounter different behavior when viewing the SWF locally versus online.As for the audio issue, you’re in luck.
It’s entirely possible to toggle audio for specific
Soundinstances. In AS2, you associate yourSoundinstance with a particular movie clip in order to provide it a kind of separate “sound channel” (see “Understanding the Sound Constructor (AS2)“); in AS3, you need an additional two classes:SoundChannelandSoundTransform.The
Soundinstance loads the file and plays it. TheSound.play()method returns aSoundChannelinstance. Finally, theSoundChannel.soundTransformproperty returns aSoundTransforminstance, which has avolumeproperty. Update that property and re-assign it to thesoundTransformproperty of yourSoundChannelinstance.It’s more convoluted, yes, but the chain of events is pretty straightforward. Thanks to the individualized sound channel, you have specific volume control over your music (or whatever else is loaded into a particular
Soundinstance).January 25th, 2008 at 1:58 am
Hello… I’ve been trying to follow the instructions above that I think apply to me, but I don’t think I have read anything that exactly covers my situation, so I’ll ask. Also, please know that I am very new to Action Script and use only very basic stuff– mostly I’m good at cutting and pasting code, so the simplest solution is best for me. Here’s my situation. I have a single timeline with a music background track that plays throughout all pages. On a couple pages I have some flv files that play and when they are selected to view, I want the background music to turn off. I have accomplished this by using the stop all sounds command on the button to launch the flv videos. When the video is over, I want to background music to start up again. So I just added another instance of the same background music to the timeline where the play head leaves the frame with the flv video. I set the sound instance sync in the property inspector to Start so that I wouldn’t get 2 of the same music tracks playing should the play head encounter this second instance while still playijng the first. This works great for turning off and on the background music when a flv file is playing. Here’s the problem… There is also a Music On and Off button (actually two separate buttons that replace one another) so that those who do not like listening to music while on the site don’t have to. I’m not quite sure what all the code is that is govering the affects of the on/off buttons (there seems to be a lot of it), but there are 2 problems. First, when you turn the button off, the video sound gets turned off also– not just the music and sound effects. That’s not good. Second, if after turning the sound off you encounter the second instance of the music on the timeline, then the music starts playing again– even though you had turned the button off. Is there a relatively simple way to solve both problems? Bottom line is that I’d like the music and sound effects to stay off when using the off button (even though play head encounters instance of music on timeline),but the off button should not kill the flv video sound. I hope this was clear. Thank you for your help.
January 25th, 2008 at 8:41 am
Earl,
Your best bet is to remove your music soundtrack from the timeline altogether. Control it using ActionScript instead. I can empathize with your hesitance to venture into unfamiliar code — at some point, all of us were beginners! — but all the same, I encourage you to ease your way into this particular approach. Even if it’s new to you, instantiating a
Soundin ActionScript 2.0 still counts as relatively basic coding. You create the instance, load a sound into it, then tell it to start and stop as you please — at any time along the timeline.It should help you considerably to read through “Understanding the Sound Constructor (AS2),” because that gives you the breakdown on what it means to separate your audio into distinct “sound channels,” which allows you to set the volume one one sound clip without affecting another (in AS2, this is done with movie clips, as you’ll see in the other article).
That will happen if you use a more global approach, like the one suggested in this article. If you route your instructions to just the video, or just the music, you’ll be fine (again, see the “Sound Constructor” piece).
That makes sense to me, because even after your button turned sounds off — using
stopAllSounds(), I think you said — the timeline overrides that and starts them up again. AllstopAllSounds()does is stop the sounds currently in play.January 28th, 2008 at 10:41 am
Hi David,
I’ve been reading through many of your blogs and have learned quite a bit so far - so thanks for that…now on to the party:
I am using Red5 to stream video to a VideoObject in Flash, using ActionScript 2 in Flash CS3. I used your technique described above (globalSound) and it doesn’t quite accomplish what I’m looking for.
I have the following code in the main timeline:
var globalSound:Sound = new Sound();
_root.muteClip.onRelease = function(){
globalSound.setVolume(0);
}
The only thing that happens when the movieClip (which is just a set of two symbols that I can toggle to the visibility to switch the display for the user) is that the sound gets a little lower, but not off…does this have something to do with streaming and NetStream/NetConnection?
Any help would be much appreciated - thanks!
January 28th, 2008 at 10:52 am
Markito,
I haven’t used Red5, so that’s a good question. In theory, streaming shouldn’t have any effect on how the
Soundclass works, but if you find otherwise, I’d love to hear about it.What I find interesting is that the sound seems to get lower, but not all the way silent. If you trace out the
globalSoundobject, do you get a valid object reference?January 28th, 2008 at 11:33 am
David,
Thanks for the speedy reply! Well, there is a lot more to this that I find incredibly confusing. If I’m using the Flash IDE the volume controls don’t work at all, meaning the volume doesn’t even get lower when I click the button. If I publish it and put it on a server to play, it then sort of responds. The second thing is that Red5 seems to operate very similarly to the Flash Media Server, so I don’t think it’s to do with Red5 either.
I tried the code you asked me to and it does come back as a valid reference. So I did a little further investigating and added some more code to the block:
_root.muteClip.onRelease = function(){
trace(globalSound);
globalSound.setVolume(globalSound.getVolume()-10);
}
After 10 clicks on the movie clip the sound was off! Then of course, I changed the above code to “globalSound.setVolume(0)” and now it works…I have no idea why this just started working almost magically. Whatever the reason, thanks for reading my post and being a fresh perspective on it. I’m not sure why it started working all of a sudden, but I’ll chalk it up to user (me!) error.
January 29th, 2008 at 10:33 am
Markito,
Ha … there’s no saying, really. I’ve seen weird things like that happen, and sometimes all that matters is that it’s working now. Glad you nailed it!
February 13th, 2008 at 6:15 pm
Hi David….I found your tutorial very interesting, especially for a beginner as myself. I have the following problem. I inserted some video clips sequentially and also have a mp3 file running on the back, however, i would like the mute the sound for these video clips (its poor quality) and prefer to have my sound of the mp3 running all the way through. Is there a script code to mute only the video clip, and if so, where do i insert this script code? Sorry if this question sounds a bit stupid, im just totally new at flash and trying to get myself going with it.
February 13th, 2008 at 7:47 pm
Bart,
Your question doesn’t sound stupid at all.
This article should get you where you’re headed: “How to Adjust the Audio Portion of Flash Video“; if not, let me know.
February 27th, 2008 at 3:16 pm
David,
I am currently working with a very simple audio toggle. I used the code
var globalVolume:Sound = new Sound();
btnSoundOff.onRelease = function() {
globalVolume.setVolume((globalVolume.getVolume()+100) % 200);
}
which was posted a while ago. It seems to work fine. The only thing I would like to do is toggle the volume button itself. When the volume is off, I would like to swap out the button for another button image, and then swap it back when the volume is on. It should seem like a simple toggle, but I’m not sure how to incorporate it into the existing code. Any help you can give me would be greatly appreciated.
Thanks
March 5th, 2008 at 6:25 pm
Hi David,
This is a brilliant blog by the way, from reading through i don’t think there
is an for my question so far. I have 6 frames on my main timeline
on the 5th frame i have 5 buttons that load in 5 different external
swf files into a blank mc. In each of the external swfs is a sound
on the timeline with a image, this all works great. I am trying to
turn the sound on and off with two buttons (which are situated
on frame 5 of the main timeline. I have tried using:
On the main timeline:
var globalVolume:Sound = new Sound();
On the buttons:
//on button//
on(release) {
globalVolume.setVolume(100);
}
//Off button//
on(release) {
globalVolume.setVolume(0);
}
This didn’t seem to work, i’m not sure but i think
this is just controlling the sound in the main flash file
and not the external swfs (i think is because of the different levels?)
sorry if this is simple, its my first time trying to control sound
using ActionScript.
Thanks
March 17th, 2008 at 9:34 pm
To Ken …
There are a number of ways you might do this. Your might, for example, use a movie clip symbol to make your button (note that the
MovieClipclass provides all of theButtonclass events, plus more). In this case, you could nest a second movie clip inside the first and give that second movie clip two frames. Use astop()action to keep the inner movie clip stopped on frame 1 to begin with. Then, in your “button” event handler (actually a movie clip event handler), you could do this:… meaning, that inner clip manages your two image states, and you send that clip to frame 1 or 2 of its own timeline in response to the toggle. Does that make sense? The only challenge there is that you lose the built-in visual states of a button symbol. But … this article may help you overcome that: “Easy Button States for Movie Clip Buttons.” You could put those visuals in the outer clip and user the inner one for the toggled state.
To Mike …
If your other SWFs are in different levels … that might just be the culprit here (but I can’t swear to that). In a sense, levels are like multiple documents in, say, Photoshop. Is there a reason you’re loading them in to levels and not movie clip instances? (Nothing at all wrong with levels, I hasten to add … they just never really clicked with me, back in the day, and I tended to prefer movie clip holders instead.)
You could certainly try creating multiple “global” volume controllers — one for each level — and set them all on/off across the board, as necessary. In that case, try …
March 30th, 2008 at 4:42 pm
Thanks so much! Very helpful.
April 3rd, 2008 at 9:37 pm
matt,
Sure thing! Glad to help.
July 25th, 2008 at 2:47 pm
Hi everyone! I’m glad to see a very nice bunch o’ folks here. Maybe you can get my mute button attempts to work? Because I’m stumped.
I’ve tried the method at the start of this tutorial. Although I think I get the concept, it won’t work in reality.
My movie doesn’t have a sound object. (I tried making one and it doesn’t work either…but that’s another story) My movie uses a sound on a layer…it’s a short sound and it loops, throughout the movie. Just FYI my movie has two scenes; once the first one is over, the second one loops.
I have been able to create a button. The button is named “Music” and it consists of the words “music on/off”. I gave it a rectangular “hit” area and an “over” and a “down” state that seem to work; it appears neatly on the movie–so far, so good. But its capability to mute the movie’s sound volume is totally nil.
Any ideas what’s happening?
Note–Given the info in the thread above, I used this:
var globalVolume:Sound = new Sound();
btnMusic.onRelease = function() {
globalVolume.setVolume(100-globalVolume.getVolume());
}
*Where* should I be putting that code? On the button itself or in the first frame of the movie? Or is something else what’s wrong?
Thanks in advance, smart Flashy people!
November 5th, 2008 at 11:17 am
HI DAVID! ARE YOU STILL HERE?
YOU WROTE:
———————
Conan,
You certainly could put the button code directly on your buttons …
As before, instantiate the Sound class first, in a frame of the main timeline.
var globalVolume:Sound = new Sound();
Then, on each of your buttons …
// on the “on” button
on(release) {
globalVolume.setVolume(100);
}
// on the “off” button
on(release) {
globalVolume.setVolume(0);
}
——————————–
IS THIS CORRECT? The layer version works fine, but my buttons do not work the way you explained to Conan.
AND WHAT HAPPENED TO THE PART: function():Void ? THIS DOES NOT SHOW UP IN THE BUTTONS CODE - AS IT DOES IN THE LAYER CODE VERSION.
I also have the problem, that the sound of a loaded swf (loaded onto an other level) should not start if the sound was silenced (setVolume(0)) before in the main swf. Otherwise I had to silence the sound twice. Is there a (simple) workaround for that?
Thanx in advance!
Robin (Designer, Non-Programmer)
November 5th, 2008 at 11:50 am
God…….n!
I just found out by myself how the buttons do work … One has to leave the WHOLE code as it is/was in the layer (not only putting: var globalVolume:Sound = new Sound(); there as explained to Conan). ADDITIONAL to that comes the button code part into the button, now it works fine!
But there is still my pre-detected sound problem of a loaded swf as mentioned above …
When the sound has already been silenced on the main level, before loading a new swf (on a new level) with sound, this loaded swf should not start its sound now. The whole movie has to stay quite.
Robin
December 1st, 2008 at 7:42 am
thank you very much! this is just what i needed
December 2nd, 2008 at 12:30 pm
You all are lifesavers.. thank you.
January 5th, 2009 at 1:05 pm
David, you da man!
I just started learning Flash, and for only 2 months in I feel pretty good about the whole affair, but I was having all sorts of issues with importing a video in swf mode, and not the flv version, and controlling the sound until I found this web site. Awesome. I put a small twist on your button call procedure and made 10 buttons and assigned a volume value for each like so:
var globalVolume:Sound = new Sound();
btnSoundOff.onRelease = function():Void {
globalVolume.setVolume(0);
}
btnSound10.onRelease = function():Void {
globalVolume.setVolume(10);
}
btnSound20.onRelease = function():Void {
globalVolume.setVolume(20);
}
//and on and on for as many buttons as needed………
This can be expanded to say 50 little buttons with 2% increases in sound value with an LED look, maybe with a little movie clip that glows on a fade up, and maybe shifting color tone as the scale increases. The current project I am working on has a few load external swf’s and when time permits I am going to experiment with just this idea.
I think I like this method better than a slider.
My question is, can the button state selected be made to “hang” in the over state until another click on another button releases it and the new selection “hangs”?
Again, wonderful source for us all, newbie and pro!
Roger Stephjenson