How to Toggle Sound Globally (AS2)

Flash ActionScript 2.0

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).

94 Responses to “How to Toggle Sound Globally (AS2)”

  1. NSurveyor Says:

    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:

    var globalVolume:Sound = new Sound();
      btnSoundOff.onRelease = function() {
      globalVolume.setVolume((globalVolume.getVolume()+100) % 200);
    }
  2. David Stiller Says:

    NSurveyor,

    That’s very cool! Done that way, you don’t even need the volumeOn variable I used in my example.

    Here’s how this one works, starting from the inside out.

    Sound.getVolume() returns the value of a Sound instance’s current volume. By default, volume is 100, so the first time this button is clicked, the value of globalVolume.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, here globalVolume.setVolume() is once again set to 100.

    Pretty slick programming!

  3. NSurveyor Says:

    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”)

  4. NSurveyor Says:

    And here’s an easier way… should’ve thought of this earlier :)

    globalVolume.setVolume(100-globalVolume.getVolume());

    When the volume is 0, it becomes 100-0 or 100, and when the volume is 100, it becomes 100-100 or 0.

  5. NSurveyor Says:

    There are a million ways of writing this!

    globalVolume.setVolume(globalVolume.getVolume()^100)
    
    0^100 = 100
    100^100 = 0
  6. David Stiller Says:

    Thanks… and if you think about it… 100/200 = 0 R100.

    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.

  7. NSurveyor Says:

    Here’s another one:

    globalVolume.setVolume(100*!globalVolume.getVolume())
    
    100*!0 = 100*true = 100; (true equivalent to 1)
    100*!100 = 100*false = 0; (false equivalent to 0)
  8. Conan Says:

    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

  9. David Stiller Says:

    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 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);
    }
  10. Uchitha Says:

    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.

  11. David Stiller Says:

    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 original Sound instance to control your global volume, and instantiate a second Sound object to hold your button sound effects. You could use the variable name sfx for that. Make sure each button has an instance name (say, button1).

    // Instantiate Sound for sfx
    var sfx:Sound = new Sound();
    // Handle Button events
    button1.onRollOver = function() {
      sfx.attachSound("UP-sound");
      sfx.start();
    }
    button1.onPress = function() {
      sfx.attachSound("DOWN-sound");
      sfx.start();
    }
    button1.onRelease = function() {
      sfx.attachSound("UP-sound");
      sfx.start();
    }

    Those three Button events represent their corresponding button symbol frames. You can use that same sfx variable for all your buttons. Each time, you’re simply invoking the Sound.attachSound() method, to attach a sound from your Library, then the Sound.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 volumeOn variable will either be true or false depending on the global volume setting. Use an if statement in your button event handlers to test whether or not to play …

    button1.onRelease = function() {
      if (volumeOn) {
        sfx.attachSound("UP-sound");
        sfx.start();
      }
    }
  12. Uchitha Says:

    Thanks :D for help, it works now !

  13. David Stiller Says:

    Glad to help, Uchitha.

  14. Karl Clay Says:

    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

  15. VD Says:

    Great post,

    thx

    VD

  16. mike Says:

    I’ve been looking for this, but in slider form. Thoughts?

  17. David Stiller Says:

    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 Sound instance, 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, and globalVolume fits the bill. :) You could have your slider set the 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.

  18. Mikaela Says:

    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

  19. David Stiller Says:

    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.

  20. Mikaela Says:

    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

  21. Kyle Says:

    Thanks dude… I’ve spent like 2 hours trying to figure this out. You’re my savior. Great tutorial!

  22. David Stiller Says:

    Kyle,

    Rock on! :)

  23. Jeremy Says:

    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.

  24. David Stiller Says:

    Jeremy,

    Glad to hear it!

  25. Jethro Says:

    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:)

  26. Casey Says:

    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?

  27. David Stiller Says:

    Casey,

    To fade sounds, you update your volume over time. You could use, say, a MovieClip.onEnterFrame handler or setInterval() to invoke Sound.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:

    var volume:Number = 0;
    this.onEnterFrame = function():Void {
      if (s.getVolume() < 100) {
        volume += 5;
        s.setVolume(volume);
      } else {
        s.setVolume(100);
        delete this.onEnterFrame;
      }
    }

    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 an onRelease handler, and contains frame labels “toggle off” and “toggle” on, with a Sound instance named s

    myButton.onRelease = function():Void {
      if (s.getVolume() == 100) {
        this.gotoAndStop("toggle off");
      } else {
        this.gotoAndStop("toggle on");
      }
    }
  28. Casey Says:

    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?

  29. Alan Fair Says:

    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!

  30. David Stiller Says:

    To Casey …

    Not sure what you mean by “global volume” parameter. In the above sample code, the letter “s” represents a Sound instance; that is, it’s a variable, s, declared earlier — not shown in the my reply sample code. A more complete sample might be …

    var song:Sound = new Sound(this);
    song.loadSound("a.mp3", true);
    song.setVolume(0);
    
    var volume:Number = 0;
    this.onEnterFrame = function():Void {
      if (song.getVolume() < 100) {
        volume += 5;
        song.setVolume(volume);
      } else {
        song.setVolume(100);
        delete this.onEnterFrame;
      }
    }

    To Alan Fair …

    Party on!

  31. Casey Says:

    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. :)

  32. Chris McLaughlin Says:

    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?

  33. David Stiller Says:

    Chris,

    Once the Library clip is attached, it becomes available to ActionScript via its instance name. Rather than constructing a Sound instance associated with the whole movie, as shown in the original article, you could construct your Sound instance and pass in, as a parameter, the instance name of the newly attached movie clip. That will associate the Sound object with that clip, controlling its audio.

  34. Chris C. Says:

    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.

  35. David Stiller Says:

    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. ;)

  36. Ryan Says:

    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.

  37. David Stiller Says:

    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 fader each time the function is called (no need to create a new movie clip object every time, especially if it’s only being used for its onEnterFrame event) — or do away with the new extra movie clip altogether by looping on setInterval().

  38. cafeine Says:

    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.!….

  39. David Stiller Says:

    cafeine,

    Glad to hear it! :)

  40. TicoXX Says:

    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..

  41. David Stiller Says:

    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.”

  42. Mike Says:

    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!

  43. David Stiller Says:

    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. :)

  44. David Stiller Says:

    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 Sound instance.

  45. Rick Says:

    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!

  46. David Stiller Says:

    Rick,

    Check out “How to Pause Sound and Resume Where it Left Off.”

  47. Rick Says:

    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.

  48. David Stiller Says:

    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 the globalVolume’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?

  49. Rick Says:

    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();

  50. David Stiller Says:

    Rick,

    In a script layer in frame 1, use this:

    var globalVolume:Sound = new Sound();
    globalSound.setVolume(0);

    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 Sound instances) — use this …

    globalSound.setVolume(100);

    … to turn up the global volume.

  51. GaryC Says:

    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

  52. varty Says:

    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

  53. David Stiller Says:

    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.onKeyUp event, rather than the Button.onRelease or MovieClip.onRelease events. The syntax is a bit more wordy, but here’s a quick example:

    var listener:Object = new Object();
    listener.onKeyUp = function():Void {
      if (Key.getCode() == 80) {
        globalVolume.setVolume(100);
      }
      if (Key.getCode() == 83) {
        globalVolume.setVolume(0);
      }
    }
    Key.addListener(listener);

    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” Object instance 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 listener object, then, stands in for the Key class and has a function assigned to its onKeyUp property. When a key is lifted (after it has been pressed), a series of if statements test to see which key was the last to be pressed; this is afforded by the static Key.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).

  54. Hardik Says:

    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

  55. David Stiller Says:

    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 globalVolume object and call its setVolume method:

    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.”

  56. luce Says:

    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

  57. luce Says:

    neah.. nevermind.. it was a silly thing.. i solve it… :)
    so complety easy.. just a loop :) )

    tnx anyway :)

  58. David Stiller Says:

    luce,

    Glad you found the fix, and glad you liked the tutorial!

  59. rick Says:

    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.

  60. David Stiller Says:

    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 Sound constructor with a timeline (a movie clip) that isn’t the main timeline. You can read more about this distinction in “Understanding the Sound Constructor.”

  61. Andy Says:

    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!

  62. David Stiller Says:

    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 native stopAllMovies() function or method in ActionScript. But I’m guessing that’s already taken care of?

  63. Andy Says:

    Nevermind! Got it taken care of. Many thanks gents!

  64. Andy Says:

    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.

  65. David Stiller Says:

    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. :)

  66. john Says:

    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!!!

  67. David Stiller Says:

    john,

    You’re welcome!

  68. Andy Says:

    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

  69. David Stiller Says:

    Andy,

    The success of your scoping is going to depend on where each of these objects resides. If you’re instantiating Sound in the same SWF that gets loaded into _level2 of another SWF, then it looks to me as if your Sound instance (sfx) is in the root of _level2, along with your buttons. The buttons should be smart enough to find sfx as shown in your first snippet.

    In AS2, the reference to sfx inside your function will look inside button1 first, hoping for a property named sfx. When it doesn’t find that, it will step up to the object that contains button1 and look there (where it should find sfx just fine). If that’s not working, that baffles me a bit, but you could certainly try an explicit reference like this:

    // In the timeline of the SWF that gets
    // loaded into _level2 of another
    var sfx:Sound = new Sound();
    button1.onRollOver = function():Void {
      this._parent.sfx.attachSound("UP-sound");
      this._parent.sfx.start();
    }

    In any case, the expression _level2._root isn’t a valid one, because _root is the base of _level2 from 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).

  70. Andy Says:

    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. :)

  71. Brian Says:

    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.

  72. David Stiller Says:

    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 [:Sound and :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 SoundTransform and SoundMixer classes in AS3: those are the ones you need to change volume globally.

    var xf:SoundTransform = SoundMixer.soundTransform;
    xf.volume = 0;
    SoundMixer.soundTransform = xf;

    In the above, xf is an arbitrarily named variable set to an instance of the SoundTransform class. Rather than the usual expression new SoundTransform(), this one gets its instance from the static SoundMixer.soundTransform property. The SoundTransform instance (xf), has a volume property, which is set to 0. The SoundMixer.soundTransform property is then set back to the updated value of xf. 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).

  73. David Stiller Says:

    [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 Sound class 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 old loadMovieNum() function), I was able to view Andy’s file as he expected and recommended that workaround.

  74. Fritz Limner Says:

    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

  75. David Stiller Says:

    Fritz,

    Your syntax is just fine for the mailto endeavor. 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 Sound instances. In AS2, you associate your Sound instance 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: SoundChannel and SoundTransform.

    var s:Sound = new Sound();
    s.load(new URLRequest("soundFile.mp3"));
    
    var c:SoundChannel = s.play();
    
    var t:SoundTransform = s.soundTransform;
    t.volume = 0; // A range from 0 to 1
    
    c.soundTransform = t;

    The Sound instance loads the file and plays it. The Sound.play() method returns a SoundChannel instance. Finally, the SoundChannel.soundTransform property returns a SoundTransform instance, which has a volume property. Update that property and re-assign it to the soundTransform property of your SoundChannel instance.

    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 Sound instance).

  76. Earl Says:

    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.

  77. David Stiller Says:

    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 Sound in 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).

    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.

    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).

    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.

    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. All stopAllSounds() does is stop the sounds currently in play.

  78. Markito Says:

    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!

  79. David Stiller Says:

    Markito,

    I haven’t used Red5, so that’s a good question. In theory, streaming shouldn’t have any effect on how the Sound class 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 globalSound object, do you get a valid object reference?

    _root.muteClip.onRelease = function():Void {
      trace(globalSound);
      globalSound.setVolume(0);
    }
  80. Markito Says:

    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.

  81. David Stiller Says:

    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!

  82. Bart Says:

    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.

  83. David Stiller Says:

    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.

  84. Ken Says:

    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

  85. Mike Says:

    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

  86. David Stiller Says:

    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 MovieClip class provides all of the Button class 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 a stop() 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:

    btnSoundOff.onRelease = function():Void {
      globalVolume.setVolume((globalVolume.getVolume()+100) % 200);
      if (globalVolume.getVolume() == 100) {
        this.innerClip.gotoAndStop(1);
      } else {
        this.innerClip.gotoAndStop(2);
      }
    }

    … 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 …

    var globalVolume0:Sound = new Sound(this);
    var globalVolume1:Sound = new Sound(_level1);
    var globalVolume2:Sound = new Sound(_level2);
    // etc.
    
    //Off button
    on(release) {
      globalVolume0.setVolume(0);
      globalVolume1.setVolume(0);
      globalVolume2.setVolume(0);
    }
  87. matt Says:

    Thanks so much! Very helpful.

  88. David Stiller Says:

    matt,

    Sure thing! Glad to help.

  89. crittermonster Says:

    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!

  90. robin Says:

    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)

  91. robin Says:

    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

  92. martin Says:

    thank you very much! this is just what i needed :)

  93. Neal Says:

    You all are lifesavers.. thank you.

  94. Roger Stephenson Says:

    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

Leave a Reply