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.)
Use anonymous FTP to download the source file folder:
Be sure to break the FTP connection to the server when done
The sound asset is stored in the Library
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
In the Actions panel (Normal mode):
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.

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.
In the Linkage Properties dialog box:
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.
(This is a name that you make up ... it doesn't have to be the same name as the sound file)
Attach Sound is the method for associating a sound asset in the Library with a Sound Object.
In the Actions panel:
(The mySound = new Sound(); statement should be selected)
(In the Object field, enter the name of the Sound Object)
(In the Parameters field, enter the Linkage Identifier of the sound)
Note: the name that you enter must be surrounded by quotation marks
With Keyframe 1 of the Actions & Labels layer still selected, and the attachSound() ActionScript line still selected, in the Actions panel:

Optionally (meaning, you do not have to do this):
The sound should play once, regardless of the length of the current scene
The initial compression amount is fairly strong, and you may hear a fairly low-fidelity sound
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
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.
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.
In the Scene panel:
With the ending Keyframe of the Actions layer selected, open the Actions panel:

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.
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.
In the Actions panel:

First we give it the name of our Sound Object instance
This tells the Sound.start() action to play the sound once from the beginning
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.
The sound will now start only when the button is clicked on
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.
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).


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


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.
With Keyframe 1 of the Actions & Labels layer (Preloader scene) still selected, and with the fourth ActionScript statement mySound.onSoundComplete ... still selected:

Expression: [ ] {deselected}
Expression: [x] {selected}

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.
The Actions panel should show:



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


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:

Expression: [ ] {deselected}
Expression: [x] {selected}

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).
Now the mySound.start() action is triggered
only if the sound is not playing
In the Actions panel:


With the mySound.stop() statement still selected:
Expression: [ ] {deselected}
Expression: [x] {selected}

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