The Sound Object
Controlling sound with precision

 

In earlier versions of Flash, there was a category of ActionScript commands called Basic Actions, which represented some of the simplest controls that anyone could use.  These included one sound control command: Stop All Sounds, which is a bit like turning off your alarm clock by smashing it with a hammer. It does the job, but not with a lot of finese.

The major difference between Flash 4 and Flash 5 (and later releases) wasn't really the replacement of modal dialog boxes with inspector panels: it is the change towards an Object orientation in the Flash environment. Macromedia has understood the needs of Web developers for years, and this is evident in the evolution of in Flash's ActionScript. Since ActionScript is based on the same standard as JavaScript, this means that any exposure or understanding of JavaScript can be applied to working in ActionScript (and the reverse is true, also).

In this exercise, sounds in Flash will be controlled by means of an ActionScript construct - the Sound Object - and ActionScript. (An "Object" is a scripting concept that represents a collection of data, and methods for manipulating that data. For example, the Date Object stores different pieces of information that relate to time, as well as methods for getting or setting different values, like the current time.)


Example

Preparation

  1. Download the source file:

    Use anonymous FTP to download the source file folder:

    1. If using a Mac, download the folder:  sound_object
    2. If using Windows, download the folder:  sound_object_win

    Be sure to break the FTP connection to the server when done

  2. Start Flash, open clips.fla, and save it to your production folder as:  sound_object.fla
  3. Modify the movie's properties:
     
    1. Modify -> Document ...
       
      1. Width:  320
      2. Height:  240
  4. Prepare the layers:
     
    1. Rename Layer 1:  Actions & Labels
  5. Create a Sound Object

  6. Import a sound file:
     
    1. File -> Import ...
       
      1. Select ragtime.aif (or ragtime.wav) (from the downloaded folder)
      2. Click:  Open

    The sound asset is stored in the Library

  7. Create a Sound Object:

    Something needs to trigger the ActionScript which creates and manipulates the Sound Object. This ActionScript can be applied to a Frame, to be triggered automatically, or to a Button instance, to be triggered by the viewer

    1. Select Keyframe 1 of the Actions & Labels layer

      In the Actions panel (Normal mode):

    2. Add Actions -> Actions -> Variables -> set variable
       
      1. Variable:  mySound
    Actions panel: Add Actions > Actions > Variables > set variable
      1. Click inside the Value field
      2. Add Actions -> Objects -> Movie -> Sound -> new Sound
    Actions panel: Add Actions > Objects > Movie > Sound > new Sound
      1. Establish the Value as an operation
         
        1. Expression:  [x]  {selected}

        When using the Normal mode of the Actions panel, you will often be confronted with the Expression checkbox.

        With Normal mode, if you want something to be treated as the name of something (as in the first case, the Variable name), the Expression checkbox is left deselected.  This tells ActionScript that you want this to be treated as the name of something (the name of the Variable).

        In the Value field, we wanted ActionScript to perform an operation - creating an instance of the Sound Object.  By selecting the Expression checkbox, ActionScript is told to treat this as an Expression ... some code that is to be acted upon.  Since the objective is to create a new Sound object, we select the Expression checkbox.

    Expression checkbox next to Value field selected
  8. Linkage Identifier

    Linkage started out as method of creating Shared Libraries - Libraries which store a Symbol separately from both the source .FLA and the exported .SWF files.  It has evolved as ActionScript has evolved, so that now it can be used to provide ActionScript with a handle by which it can manipulate Library items/assets.

    Generally, ActionScript needs to address something by name, if it is to manipulate it.  A Symbol name, like a Layer name, is just for the use of the Flash author ... it is not a name that Flash/ActionScript can make use of.  Because of this, if we want to manipulate a Library asset - and we do if we want to use the imported sound with the Sound Object - then we need to establish this name - this Linkage Identifier - so that ActionScript can manipulate the Library asset.
     

  9. Apply an Indentifier to the sound in the Library:
     
    1. Select the sound ragtime.aif (or ragtime.wav) in the Symbol Library
    2. Panel Options -> Linkage...

      In the Linkage Properties dialog box:

      1. Linkage:  Export for ActionScript:  [x]  {selected}

        This automatically enables the Export in First Frame checkbox.

        There is a specific and unavoidable consequence to having the Export in First Frame setting selected, and that is that this entire asset will be downloaded before the first frame is played.

        It makes sense that this asset (sound) must be downloaded before we can use it.

        But it will create some havoc when working with Preloaders ... the Flash player will not play the first frame of the movie until this asset has been completely downloaded ... and most preloaders are initiated in the first frame of the movie.  Any such preloaders or ActionScript statements placed on the initial Keyframe of the movie will not be acted upon until after all assets which have Export in First Frame associated with them have been completely downloaded.

      2. Identifier:  oldie

        (This is a name that you make up ... it doesn't have to be the same name as the sound file)

      3. Click:  OK
  10. Panel Options -> Linkage...: select Export for ActionScript and enter Indentifier (name)

    Attach Sound

          Attach Sound is the method for associating a sound asset in the Library with a Sound Object.
     
  11. Select Keyframe 1 of the Actions & Labels layer
  12. Attach a sound to the Sound Object:

    In the Actions panel:

          (The  mySound = new Sound();  statement should be selected)

    1. Add Actions -> Objects -> Movie -> Sound -> Methods -> attachSound
  13. Add Actions > Objects > Movie > Sound > Methods > attachSOund

        (In the Object field, enter the name of the Sound Object)

      1. Object:  mySound

        (In the Parameters field, enter the Linkage Identifier of the sound)

      2. Parameters: "oldie"

        Note: the name that you enter must be surrounded by quotation marks

    sound_attached.gif

    Play the Sound

  14. Play the sound:
     

    With Keyframe 1 of the Actions & Labels layer still selected, and the attachSound() ActionScript line still selected, in the Actions panel:

    1. Add Actions -> Objects -> Movie -> Sound -> Methods -> start
  15. Actions > Objects > Movie > Sound > Methods > start
      1. Object:  mySound
      2. Parameters:  {leave empty}
    mySound.start() complete

          Optionally (meaning, you do not have to do this):

        1. Enter the seconds Offset:
          1. Enter however many seconds into the sound you want the sound to begin playing.   The sound will begin playing immediately at however many seconds you enter
            Leaving this empty is the same as entering: 0 seconds
            Offset refers to how many seconds from the beginning of the sound it should start playing. This is not a delay before beginning the sound ... it is how many seconds into the sound should it begin to play immediately
        2. Enter a comma
        3. Enter the loop count:
          1. Enter the number of times to loop the sound
            Leaving this empty is the same as entering:  1       
    Sound.start() parameters filled in
        1. Leaving the Parameters field empty is the same as entering:  0,1
  16. File -> Save, and Control -> Test Movie
  17. The sound should play once, regardless of the length of the current scene

  18. Adjust the compression settings for this sound

    The initial compression amount is fairly strong, and you may hear a fairly low-fidelity sound

    1. Select the sound asset in the Library (select the name of the imported sound)
    2. Panel Options -> Properties ...
       
      1. Compression -> MP3
      2. Bit Rate -> 24 kbps
      3. Convert to Mono:  [  ]   {deselected}
      4. Quality -> Best

      Note: Audio compression settings are like JPEG compression settings: the better the quality, the greater the file size.  And like JPEG compressions settings, no one setting or groups of settings will be optimal for every sound ... they compression settings must be set on a case by case basis, and as with JPEG compressions, you should always evaluate the results

    3. Click:  Test
    4. Click:  OK
  19. Preparations II

    Basically, it takes two ActionScript statements to establish a Sound Object.  It takes one additional ActionScript statement to start the sound, and another one to stop the sound.

    Actions appllied to frames are triggered automatically when the playback head enters the keyframe containing the ActionScript statements.

    Actions applied to Button instances turn control over to the user.

    Next, let's see how valuable the Sound Object is, by creating a multi-scene movie, and establishing start() and stop() sound actions to the buttons.

  20. Remove the last frame action that starts the sound:
     
    1. With Keyframe 1 of the Actions & Labels layer selected, in the Actions panel, select the 3rd ActionScript line:  mySound.start( 0, 1 );  and delete it by clicking on the [-] Delete the Selected Actions button

      By removing the start() ActionScript statement, the Sound Object will be created, and a sound from the Library attached, but the sound itself will not begin playing.

  21. Prepare the Scenes

    In the Scene panel:

    1. Rename Scene 1:  Preloader
    2. Insert a new scene, and name it:  Scene 1
    3. Insert a new scene, and name it:  Scene 2
    4. Insert a new scene, and name it:  Scene 3
    5. The play order should be:  Preloader, Scene 1, Scene 2, Scene 3
    6. Prepare Scene 1:
       
      1. Switch to  Scene 1
      2. Rename Layer 1:  Visuals
      3. Insert a new layer, and name it:  Buttons
      4. Select the Visuals layer
      5. Drag an instance of the Movie Clip symbol  1  onto the Stage
      6. Name the 1 instance:  one_mc
      7. Select the Buttons layer
      8. Drag an instance of the Button symbol  Button On  onto the Stage
      9. Name the Button On instance:  startSound_btn
      10. Drag an instance of the Button symbol  Button Off  onto the Stage
      11. Name the Button Off instance:  stopSound_btn
      12. Extend both layers to frame 19
    7. Prepare Scene 2:
       
      1. Switch to  Scene 2
      2. Rename Layer 1:  Visuals
      3. Insert a new layer, and name it:  Buttons
      4. Select the Visuals layer
      5. Drag an instance of the Movie Clip symbol  2  onto the Stage
      6. Name the 2 instance:  two_mc
      7. Extend both layers to frame 19
    8. Prepare Scene 3:
       
      1. Switch to  Scene 3
      2. Rename Layer 1:  Visuals
      3. Insert a new layer, and name it:  Buttons
      4. Select the Visuals layer
      5. Drag an instance of the Movie Clip symbol  3  onto the Stage
      6. Name the 3 instance:  three_mc
      7. Extend both layers to frame 19
      8. Insert a new layer, drag it above the other layers, and name it:  Actions
      9. Insert a keyframe at the last frame of the Actions layer
      10. Apply a GoTo action to the ending keyframe of Scene 3

        With the ending Keyframe of the Actions layer selected, open the Actions panel:

        1. Add Actions -> Actions -> Movie Control -> goto
    Add Actions > Actions > Movie Control > goto
          1. Go to and Play:  (*)   {selected}
          2. Scene -> Scene 1
          3. Type -> Frame Number
          4. Frame:  1
  22. What was established in this step was some visual content which tells us which scene we are in when we are testing the movie.

    The goto Action directs the movie to go to Scene 1, Frame 1, and continue playing.  There was a scene, Preloader, established before scene 1.  While it technically does not do anything typically associated with a Preloader, it does do one thing we don't want repeated: establishing a Sound Object, and attaching a sound from the Library.  That only should only be done once during the life of the movie.

    By applying the goto action to the last frame of the movie, and telling it to go back to Scene 1 and continue playing, we prevent the movie from automatically looping back to the beginning of the movie, which is the Preloader scene.

    At this point, there are buttons only in Scene 1.

  23. Switch to Scene 1 
  24. Power to the People: Button Actions

    Remember:

    When working with the Actions panel, pay very close attention to what the Title Bar and the Navigate To Other Scripts menu are telling you.

    It is very easy to select a Frame when you mean to select an Instance on the stage, and it is very easy to select an Instance when you mean to select a Frame.

    The only way you can be assured that you have the right thing selected is to look at the Actions panel and register what it is telling you.


  25. Apply a  Sound.start()  action to the button instance named startSound_btn:
     
    1. Select the button instance named:  startSound_btn
    2. In the Actions panel:

    3. Add Actions -> Objects -> Movie -> Sound -> Methods -> start
  26. Add Actions > Actions-> Objects > Movie > Sound > Methods > start
      1. Object:  mySound
      2. First we give it the name of our Sound Object instance

      3. Parameters:  {leave empty}
      4. This tells the Sound.start() action to play the sound once from the beginning

    mySound.start() applied to button

    When working in Normal mode and an action is applied to a button instance, Flash automatically wraps the default button Event Handler around the statement.

    The  on(release)  Event Handler is the default trigger for button actions: when the user clicks on this button, and releases the mouse button, then this  mySound.start()  action is triggered.

  27. File -> Save, and Control -> Test Movie
  28. The sound will now start only when the button is clicked on

  29. While the movie is still playing in Scene 1 (you'll have to be quick), click repeatedly on the  startSound_btn  button
  30. Each time the button is clicked, a new copy of the sound begins playing ... ultimately, you will end up with multiple copies of the sound playing

    This would not be a problem if you were using a Toggle Clip, as shown in the Working with Sound handout.

    However, here's where knowing a little bit about ActionScript and scripting, or knowing or working with someone who does, can make a big difference in a Flash project.  We can use ActionScript to check to see if the sound is playing, and only if it is not playing allow the mySound.start() action to be triggered.

    ActionScript to the rescue

    To prevent the repeated triggering of the sound (to prevent multiple copies from playing at one time), we will need to keep track of the sound's playing status:  Is it currently playing? ... then we don't want to trigger a new Sound.start() action.  Is it currently not playing? ... then it is OK to start playing.

    ActionScript can provide mechanisms for this kind of detection.  Specifically with the Sound Object, there is an Event (a trigger) which we can use to detect if a sound has finished playing: onSoundComplete.

    We will establish a variable which we will use to keep track of the current status of the sound ... specifically whether the sound is currently playing or not.

    The Toggle Clip concept is a superior solution, and is the better mechanism for providing user-control over the sound.  If you don't want to look at ActionScript in this depth, skip over this section and go on to the Stop a Sound from a Button section below.  Those who are curious may be very interested in the following for what it implies ...

    The use of the Sound Object does not require the next few steps.  These steps can be avoided entirely by using the Toggle Clip construct. They are shown for the sake of completeness, and to show that ActionScript can be used to solve design problems.

    You may skip these next 5 major steps entirely, and jump in at the Stop a Sound from a Button section (internal link).


  31. Establish a variable that we will use to keep track of whether or not it is OK to play the sound:
     
    1. Switch to editing the Preloader scene
    2. Select Keyframe 1 of the Actions & Labels layer
    3. Select the last ActionScript statement:  mySound.attachSound("oldie");
    select the last statement
    1. Add Actions -> Actions -> Variables -> var
    2. Variables:  OKToPlay = true
    establish vaiable: OKToPlay with initial value of TRUE

    We are doing two things in this one statement:

    We are formally declaring a variable named OKToPlay.

    We are assigning it an initial value.  The initial value is a special value, a Boolean value, of true.  Boolean values (which can only be true or false) are handy in situations like this ... we want to keep track of a situation that is either true (OK to play the sound) or false (not OK to play the sound).

    Logically, when the playback head of the movie sweeps through this frame, the user has not had a chance to click on the button with the mySound.start() command.  So at this point, it is OK to play the sound, since the sound has not been started by the user.

  32. Keep track of when the sound has finished playing

    There is a mechanism that is part of the Sound Object which is aware of when a sound has finished playing.  It is the onSoundComplete() Event Handler.  An Event is like a trigger; in this case, the Event is the sound finishing playing.  We will use this triggering event to change the value stored in the variable OKToPlay, so that it reflects that it is now OK to play the sound (again).

    With Keyframe 1 of the Actions & Labels layer (Preloader scene) still selected, and with the third ActionScript statement  var OKToPlay = true;  still selected:

    1. Add Actions -> Objects -> Movie -> Sound -> Events -> onSoundComplete
  33. Objects > Movie > Sound > Events> onSoundComplete
    1. Object:   mySound
    associating the onSoundComplete event with the mySound object

    This associates the onSoundComplete Event Handler with our mySound Object.  There can be many Sound Objects in existence at one time, so we need to specify which one we want to keep track of.

  34. When the sound has finished playing, set the OKToPlay variable to true:
  35. With Keyframe 1 of the Actions & Labels layer (Preloader scene) still selected, and with the fourth ActionScript statement  mySound.onSoundComplete ...  still selected:

    1. Add Actions -> Actions -> Variables -> set variable
    change variable value when sound complete
    1. Variable:  OKToPlay
    2. Expression:  [ ]   {deselected}

    3. Value:  true
    4. Expression:  [x]   {selected}

    When sound complete, set OKToPlay to true

    What this is doing is: when the sound has finished playing, set the variable OKToPlay to true.  While this may seem odd, having just set this variable to true in the previous step, we are setting this up for some point in the future, after the user has clicked on a button to initiate the sound playing.

  36. Modify the ActionScript applied to the startSound_btn button instance, so that it only plays the sound if it is OK to play the sound (the sound is not currently playing):
     
    1. Switch to editing Scene 1
    2. Select the startSound_btn button instance
    3. The Actions panel should show:

    the Actions panel with the startSound_btn instance selected
    1. Select the first ActionScript statement:  on (release)
    select the on (release) statement
    1. Add Actions -> Actions -> Conditions/Loops -> if
    Condition: OKToPlay
    1. Condition:  OKToPlay
    2. The if() construct allows us to take certain actions IF the condition it is evaluating is true.  In this case, we are testing to see if the value held in the variable OKToPlay is true or false.  If it is true, we want to allow the user to start the sound.

    3. Move the mySound.start() statement so that is within the if () conditional statement's open and closing curly brackets { }
    4. Curly brackets are a way of grouping one or more statements together. We have the potential to execute more that one ActionScript statement if a condition is found to be true.

      1. Select the mySound.start() statement
    Select the mySound.start() statement
      1. Click once on the Move the selected action(s) up button, to change the position of the  mySound.start()  statement so that it is placed between the open and closing curly brackets of the  if()  statement
    mySound.start() moved within if() curly brackets
  37. Set the variable  OKToPlay  to false
  38. If it is OK to play the sound when the user clicks on this button, the mySound.start() statement will be executed ... meaning that the sound is now playing.  We specifically do not want the sound to begin playing a second time.  So that now that the sound is playing, we want to set the variable OKToPlay to false, because it is not OK to play the sound again until it finishes playing.

    With the startSound_btn button instance still selected, and with the mySound.Start() statement still selected:

    1. Add Actions -> Actions -> Variables -> set variable
    mySound.start() still selected
    1. Variable:  OKToPlay
    2. Expression:  [ ]   {deselected}

    3. Value:  false
    4. Expression:  [x]   {selected}

    OKToPlay set to false

    To summarize:  When the user clicks on this button, if it is OK to play the sound (it is not already playing), start playing the sound, and set OKToPlay to false (because now that the sound has started playing, it is no longer OK to play the sound).

  39. Save and Test Movie
  40. Now the  mySound.start()  action is triggered only if the sound is not playing

    Stop the Sound from a Button

  41. In Scene 1, select the stopSound_btn Button instance
  42. Attach a  Sound.stop()  action to the button instance:

    In the Actions panel:

    1. Add Actions -> Actions -> Objects -> Movie -> Sound -> stop
  43. Sound Methods stop
    1. Object:  mySound
    mySound.stop()
  44. Set the variable  OKToPlay  to true
  45. With the  mySound.stop()  statement still selected:

    1. Add Actions -> Actions -> Variables -> set variable
       
      1. Variable:  OKToPlay
      2. Expression:  [ ]   {deselected}

      3. Value:  true
      4. Expression:  [x]   {selected}

    set OKToPlay to true

      When this button is clicked, the sound is stopped.  Even if you did not perform the earlier ActionScript steps, this will do no harm.  But if you did, then we are changing the value of the OKToPlay variable to reflect the current conditions (that it is OK to play the sound, now that the sound is stopped).

  46. Save and Test Movie
     
          If you performed all of the steps in this handout, the sound will now start only when the button is clicked on.  But if you did not, and just performed the mySound.start() and mySound.stop() portions, the buttons now turn control of the sound playing over to the user.

  47. Copy buttons

    Finally, let's copy the button instances into the other two scenes.

    This was held off until last to demonstrate an important point: when you copy instances from one place to another, any ActionScript statements which have been applied to the instances are copied along with the instances themselves.

    Had we copied the buttons into the other scenes first, we would now have to go and apply the same ActionScript to them as we did to these two instances.

  48. In Scene 1, select both button instances, and:  Edit -> Copy
  49. Switch to Scene 2, select the Buttons layer, and:  Edit -> Paste in Place
  50. Switch to Scene 3, select the Buttons layer, and:  Edit -> Paste in Place
  51. Save and Test Movie
     

The sound can now be controlled anywhere in the movie, without worrying about a layer ending prematurely stopping a sound. By copying and pasting in place, the buttons appear in the same location in each scene, so the user is not aware that you have constructed the movie in scenes.

The ActionScript to the Rescue section is not necessary for understanding how the Sound Object works or can be controlled via button actions ... but it does show how ActionScript can be used to solve design problems.  A preferable alternative would be using the Toggle Clip concept, because then the start/play button is "hidden" and replaced by the stop button when the start/play button is clicked.

The actual ActionScript for creating a Sound Object and associating a sound with it takes only two ActionScript statements; the start and stop button actions each only required two statements, one of which was done for you by the Normal mode of the Actions panel.

 

copyright© 1999 - 2003 Stephen McManus July 16, 2003
Home