Monday, January 17, 2011

AS3 - Play Sound from Library

Exercise File:
claps.wmv

*Sound loop created by Brad Sucks.

In this tutorial, we're going to learn how to use ActionScript 3 in order to control sound. This lesson comes with an audio file, which you can download from the link above. The file is named claps.wav, which is a short 4-second sound file.

We will be importing the sound file into the Flash document's library. But instead of adding the sound to the timeline, we'll be accessing it using ActionScript code. We'll also learn how to make the sound loop using the AS3 Event.SOUND_COMPLETE event.

NOTE: WAV files are ideal for sound loops, because they can be made to loop seamlessly. MP3 files, on the other hand, are NOT good for looping. MP3 files are not ideal for sound loops because MP3 audio files have a short silent gap at the end (due to the compression algorithm being used). So if you loop an MP3 file, you will have these short silent gaps in between each loop that make the loop sound as if it's skipping.

Step 1

Let's start by creating a new Flash ActionScript 3 Document.

Step 2

On the stage, let's draw 2 buttons - a play button and a stop button. We'll be using these buttons to start and stop our sound. Let's give the the play button an instance name of play_btn and stop_btn for the stop button.

Step 3

Once you have the buttons, let's go ahead and import the claps.wmv audio file into the Flash document's library. From the main menu, choose File > Import > Import to Library. Navigate to where the claps.wmv file is in your computer and import the file. When importing is done, you should see the audio file in the Flash document's library.

Step 4

At this point, let's set up the sound file in our library so that we will be able to access it using ActionScript. To do that, right-click on the sound file in the library and choose Properties.
 
When the Sound Properties dialog box comes up, go to the part that says Linkage. If you don't see this area, click on the Advanced button at the bottom of the dialog box. Once you see the Linkage options, make sure that the following are checked:
  • Export for ActionScript
  • Export in frame 1
This will ensure that our audio file will be exported for ActionScript so that we can control it using code. Export in frame 1 means that the audio file will be exported to frame 1. That way, the sound file will be available to us from the very beginning of the Flash movie. But this does not mean that the sound will play immediately. It simply means that it's available to us starting from the very first frame.

Step 5

After we've checked those options, you'll see a couple of input fields become accessible right below the check boxes. Go to the Class input field and change the name to Claps. This allows us to create a class from our audio file. We will use this class in order to create an instance of our claps.wmv sound file, so make sure you remember this name (Claps) because we will use it later on.

NOTE: This class name is author defined. You can give it any name you want as long as it does not conflict with other class names in your project. The class name is case-sensitive.

Step 6

Double-check to see if you've set everything up properly and then click on OK. You will then get a message that says: A definition for this class could not be found in the classpath, so one will be automatically generated in the SWF file upon export. Click OK so that the Claps class will be generated once you export your SWF.

Now that the sound file in our library is properly set up for use with ActionScript, let's go ahead and write some code.

Step 7

Create a new layer for the Actions, select the first keyframe of that layer, and launch the Actions Panel.

Step 8

Let's go ahead and create an instance of the claps.wmv sound. Remember that the class name we specified is Claps. So type the following line in the script pane:
var clapsSound:Claps = new Claps();
Here, we've created a new instance of the Claps class, which is the class name that we assigned to the claps.wmv file in our library. We've named this instance clapsSound. To hear the claps.wmv audio file, we simply have to play the clapsSound instance. You can do this using the play() method. But before we do that, let's add event listeners to the buttons that we made earlier.

Step 9

So let's go ahead and create mouse click event listeners for our play (play_btn) and stop (stop_btn) buttons:
var clapsSound:Claps = new Claps();

play_btn.addEventListener(MouseEvent.CLICK, playSound);
stop_btn.addEventListener(MouseEvent.CLICK, stopSound)

function playSound(e:MouseEvent):void
{

}

function stopSound(e:MouseEvent):void
{

}
Here, we've created 2 event listener functions - playSound for playing the sound, and stopSound for stopping the sound.

Step 10

Inside the playSound event listener function, let's use the play() method of the Sound class in order to instruct the sound to start playing once the button is clicked:
function playSound(e:MouseEvent):void
{
     clapsSound.play();
}
So now, if you test the movie, clicking on the play button will start playing the sound. We'll learn how to stop the sound in the next step.

Step 11

For stopping the sound, we'll need to create another object of a different type. Simply adding clapsSound.stop() will NOT work, because the stop() method for sounds belongs so another class - the SoundChannel class. And after we've created this SoundChannel object, we'll need to assign clapsSound.play() to it. This will allow us to stop the sound using the stop() method of the SoundChannel class:
var clapsSound:Claps = new Claps();
var clapsChannel:SoundChannel = new SoundChannel(); 
// our SoundChannel object

play_btn.addEventListener(MouseEvent.CLICK, playSound);
stop_btn.addEventListener(MouseEvent.CLICK, stopSound)

function playSound(e:MouseEvent):void
{
     clapsChannel = clapsSound.play();
     // assign the play() method call to the
     // SoundChannel object
}

function stopSound(e:MouseEvent):void
{
     clapsChannel.stop(); 
     // use the stop() method of the
     // SoundChannel class to stop the sound
}
So if we test the movie at this point, we can now successfully play and stop our library sound.

In the next part of this article, we'll learn how to make the sound clip loop.

Making a Sound Clip Loop in AS3

If we want to make the sound loop, we'll need to find a way to be able to tell it to play again once the sound has completed the playback (i.e. when it reaches the end). We can use the SoundChannel class to achieve this. The SoundChannel class has an event associated with it called Event.SOUND_COMPLETE. This event gets dispatched whenever a sound that's playing in a SoundChannel has completed playback. So we can create an event listener for this event, and then tell the sound to play again once this event gets dispatched (i.e. tell the sound to repeat when it reaches the end).

Let's go ahead and create the event listener function first. Let's name it loopSound. Inside this listener function, we'll instruct the sound to play again. So we'll need to add another call to the sound's play() method statement inside this new function:
function playSound(e:MouseEvent):void
{
     clapsChannel = clapsSound.play();
}

function stopSound(e:MouseEvent):void
{
     clapsChannel.stop();
}

function loopSound(e:Event):void
{
     clapsChannel = clapsSound.play();
     trace("The sound has reached the end");
}
I've added in a trace statement so that we will get a message from the Output window once the sound has reached the end.

So, now that we've created this listener function, let's go ahead and register it to our SoundChannel object (clapsChannel).

If you're registering an event listener function to the Event.SOUND_COMPLETE event of the SoundChannel class, you must add the event listener only AFTER the sound has been assigned to the SoundChannel (i.e. it must be added after the SoundChannel = Sound.play(); statement). In our example, the first time the sound plays will be when we click on the play button. So we must add the Event.SOUND_COMPLETE listener after the clapsSound.play() statement inside the playSound() function:
function playSound(e:MouseEvent):void
{
     clapsChannel = clapsSound.play();
     clapsChannel.addEventListener(Event.SOUND_COMPLETE, loopSound);
}
So now, go ahead and test your movie. When you click on the play button, the sound will start playing. And then when it reaches the end, you will see a message from the Output window (from our trace statement), and the sound will immediately play again.
After you've tested the movie and played the sound, you will notice that the sound will only repeat ONCE. After the second time it plays, it will no longer repeat itself. So here, we see that the Event.SOUND_COMPLETE listener will only listen out for the event ONCE. It's not going to keep watching out for Event.SOUND_COMPLETE indefinitely.

But what if we want it to listen out for Event.SOUND_COMPLETE indefinitely so that we can make our sound loop indefinitely as well?
In order to do that, we'll need to add the event listener AGAIN after it begins playing the succeeding time. So we'll also need to add the Event.SOUND_COMPLETE listener inside the loopSound() function right after the sound plays:
function loopSound(e:Event):void
{
     clapsChannel = clapsSound.play();
     clapsChannel.addEventListener(Event.SOUND_COMPLETE, loopSound);
}
So now, we have the add event listener statement for the Event.SOUND_COMPLETE listener in both the playSound() and loopSound() functions. That way, each time the sound plays, Flash will watch out for when the sound completes the playback and will play the sound again. This results in a sound file that loops indefinitely.

NOTE: If you want more than one sound clip to loop simultaneously using this method, then you'll have to create one SoundChannel for each sound.

And that concludes this tutorial on how to play sound from the library using AS3 and AS3 sound looping.

15 comments:

  1. Thanks for the tutorial. I was trying to figure out how to exectue a fuction after sound has finished playing in my flash video. I used your example "clapsChannel.addEventListener(Event.SOUND_COMPLETE, loopSound);" and then in the funtion loopSound, I added the rest of my action codes. Worked Perfectly.

    ReplyDelete
  2. You're welcome! Glad this helped you out. If you could give us a like on facebook that would be great! Have a nice day! :)

    ReplyDelete
  3. How do I call the function? I called loopSound() and it says I need 1 argument. It makes sense, but I don't know what argument to give it.
    Thanks

    ReplyDelete
  4. The argument is the event object. Since loopSound is an event listener, it gets called after the event is dispatched (SOUND_COMPLETE in this case).

    ReplyDelete
  5. i get some latency and i already checked my audiofile??? please help

    ReplyDelete
  6. Try making sure that your audio file's sampling rate is at least 41kHz

    ReplyDelete
  7. Thx! I've been struggling with this in Flash for weeks now and this makes it clearer to me.

    ReplyDelete
  8. I have 4 sounds I want to play. The first works beautifully but the others don't. Each has their own instance, and own buttons, but I have dead stop/play buttons.

    ReplyDelete
  9. Thanks a lot..Your solution helps me...

    ReplyDelete
  10. Thanks a lot...you solved my issue related to loop...

    ReplyDelete
  11. I have a very short (.005 seconds) WAV file (44.1 kHz) that is a single wave cycle of a bee's buzz. I want to loop this WAV file seamlessly to create a buzzing bee sound that I can adjust the pitch, volume, and pan of. The loop I get using this code doesn't cycle quickly enough to make it sound like a buzz. I am afraid that if I use a longer WAV file, the changes will be choppy. Any suggestions?

    ReplyDelete
  12. Why on earth would anyone do sound looping this way when AS3 has it built in already?!

    yourSoundName.play(StartTime,#loops)

    ReplyDelete
    Replies
    1. The loops parameter of the Sound.play() method allows you to define a specific number of times for the sound to loop. But if you don't have a specific number in mind, and just want the sound clip to loop indefinitely, then you can use the SOUND_COMPLETE event handler as demonstrated in the example. But really, the main thing I want readers of this tutorial to learn from that part of this tutorial is that there is a SOUND_COMPLETE event that they can use for a variety of different things in their projects. So think of this more as an example for learning.

      Delete
  13. how do one play the sound once only!! if you see when you click again on the play button it repeats the sound again n so on how do you play it once only. any suggestion

    ReplyDelete