LiveMotionCentral - A Resource Site for Adobe LiveMotion
Tutorial


 Getting Started
 Animation
 Optimization
 Interactivity
 Sound
 Physics
 Dynamic Content
 Player Scripting
 App. Scripting
 Additional Utilities

 LiveMotion™ 1

 Add a Tutorial

more »

Latest News

 LiveMotion 2
 GoLive 6
 Interviews
 News Letter
more »
Audio Player Tutorial LiveMotion 2.0 Beginner Download
  By: Iain Houston
Email: Iain@HePlaysJazz.co.uk
URL: www.HePlaysJazz.co.uk
05.18.2002  
 

This tutorial explains how to write a few scripts that control the playing of a large sound file.

 

 
 

My original application is an animation whose frames are synchronized to the beats of a piece of music. The tutorial doesn't deal with every aspect of this application, but focuses on a couple of common problems we are likely to come across frequently with this kind of thing.

  • A multi-state 'play' button.
  • Efficient downloading of the sound.
  • Responding to 'asynchronous' user interactions for starting and stopping the sound.

Before we go any further with this I should say that this tutorial is very LM2-specific: it takes advantage of two major features that are in LM2 to make the scripting nice and simple:

  • a bit of Javascript not present in Actionscript
  • LM-managed movieclip states

The scripting is simple.

Don't be put off by the first bit of the tutorial. The later scripting is the easy part to follow. But there are many details early on in the way the objects are created in the compositions that are important to understand. They say the devil's in the detail!

The sound

Let's get this out of the way first. It's very easy to do, but there are some very important things to note.

Sound files are big. So this solution splits up the sound from the player.

  • The File >> Place command is used to add a .WAV file into an empty composition as shown above. This original file (GSClip.wav) is 4.46 Mb. But LM2 will compress this into an MP3 file embedded in the .SWF file.
  • I specified in the Export palette that I wanted LM2 to make me a Flash file (.SWF) and that I wanted reasonable sound quality so I chose an MP3 compression of 80 kbps and for the sound to remain in stereo. Remarkably, LM2 gave me a Flash file of just 267K! I have a good sound card (made by Terratec) on a PIII system and the quality of the compressed sound is good. LM2's MP3 encoder is evidently a good one - you can see the Fraunhofer and Thomson multimedia credits on the LiveMotion About panel.
  • Most importantly you must specify Streaming sound in the Properties palette. If you don't you won't be able to stop and start the sound at will. Streaming sound is synched to the animation frames. The other kind - Event sound - is not.
  • I dragged the streaming sound clip's timeline slider so that the sound didn't start on frame 1.
  • I added a script at frame 0 telling the whole movieclip to stop. If you don't do this a movieclip will start playing as soon as it's loaded. Not what we want in our case. (See the script statement in the script editor at frame 0 above).
  • You'll also see I added a label "theBeginning" near where the sound starts. This will be used by the player to gotoAndPlay("theBeginning"); or to gotoAndStop("theBeginning");. Because the Actionscript is interpreted at runtime (rather than compiled) the Flash runtime can resolve these labels even though they exist in different SWF files. (But there is a price to pay for this! See "Debugging" below.)
  • In the picture below you'll see that I added a script after the last frame of the sound to set the play button state when the sound finishes.

As for the sound: that's it! Just one label and two script statements:

  1. One stops the sound from playing before we want it to.
  2. The other communicates with the player automatically when the sound comes to an end. _level0._root.playButton.lmSetCurrentState("stopped");

Debugging

Although this is a working example and I've included all the script in this tutorial (and there's not a lot of it!) if you use this as the basis of your own development I suggest you comment out the Javascript that is not supported in the previewer/ debugger and add some "testing only" statements as you build it into your own application. The LM2 previewer (obviously I suppose) cannot deal with loadMovieNum() and movieclip._framesloaded; which makes some things quite difficult to debug. Similarly, the Flash runtime is clever enough to resolve labels declared in two different SWF files; but if you make one tiny typo things won't work as you expect and it'll be difficult to see why.

The player

Let's look at what he player is made up from.

  1. A preloader for downloading the sound in the background while the user interacts with other parts of the web page. The preloader is very simple but it will display the progress of the download.
  2. playButtonText which describes the state of the play button: whether it's already playing; stopped and ready to play; or not yet ready to be pressed because the sound hasn't completely downloaded.
  3. The playButton itself which, when ready, will start and stop the playing of the sound.

The play button

I dragged in the play button from the Library palette and created two new custom states as shown here. By creating additional states LM automatically turns the button into a movieclip. The purpose of the "playing" and "stopped" states is obvious, but the default "normal " state represents the player when it is not yet ready to play: when the sound is still loading.

At this point it's worth noting several things about LM's concept of movieclip states.

  • They are really convenient in that LM manages the automatic changes to the movieclip's appearance: So when my script sets the button to its "stopped" state, it will automatically change to purple. Moreover, I can add State scripts to apply all sorts of side-effects from the state change including stopping the sound! Just what we want!
  • But take care with the normal state. Like the onLoad method, it can get invoked very early on in the composition's lifetime before other visible objects have been brought to life so you need to be careful that your added script doesn't rely upon the existence of other objects. For example I can't put script in the playButton's normal state to make the playButtonText say "loading".
  • Also think twice about using LM's standard states like down because this will generate event handler scripts (in this case in the onButtonRelease handler) that will automatically set the button back to its normal state. And you can't delete this automatically-generated scripting either; for very good reason: so in our case a two-state button is not really what we want so we can choose to use the custom-states rather than the more usual 'rollover states'. Again this is just what we want.
  • The way LM2 treats movieclip states relates to well-established and theoretically very sound programming practices you could derive from Tony Hoare's Communicating Sequential Processes or the highly recommended Concurrency: State Models and Java Programs by Jeff Magee and Jeff Kramer.

Play button scripts

Handler scripts

onLoad handler

We declare a variable to keep a record of the state of the play button; because we have chosen to maintain a 3-state button rather than LM's standard kind. Initially the button is not ready for use as the sound's movie clip is still loading.

var buttonState = "notReady";

onButtonDown handler

Initially the play button is inactive ... until the sound has been loaded. This is Javascript that is LM2-specific. The switch makes simple to read script. LM2 will translate this into other Actionscript constructs when it exports the SWF file.

This combination of this switch and the changes of state is quite elegant - in practical terms making a more readable and less error-prone piece of script.

switch(this.buttonState){

case "playing": // loaded and playing

this.lmSetCurrentState("stopped"); // stop the playing

break;

case "stopped": // loaded but not playing

this.lmSetCurrentState("playing"); // start the playing

break;

default: // "notReady"

; // ignore button press

}

State scripts

stopped state script

The user has pressed the playButton when music is aleady playing and the button text says 'stop'. Or the preloader has finished loading. Or the sound movie clip has reached its end. So we put the play button into its "stopped" state.

Earlier in the tutorial you saw where we decalred the label "theBeginning" in the sound's movieclip. And below you'll see us loading the sound's movieclip into _level5. So the script below should make sense.

this.buttonState = "stopped" ; // turn it into a 'play' button

_root.playButtonText.lmSetCurrentState("sayPlay");

_level5._root.gotoAndStop("theBeginning");

playing state script

this.buttonState = "playing";

_level5._root.gotoAndPLay("theBeginning");

_root.playButtonText.lmSetCurrentState("sayStop");

The playButtonText movieclip

It's created using the type tool. It indicates what state the playButton is in: the default "normal" state says that the sound is still loading. Again two additional custom states are created: "sayStop" and "sayPlay" for when the music is playing and stopped respectively.

There are no scripts for the playButtonText. The playButton script shown above invokes the state-changing calls: the rest is managed by LM2.

The preloader

This is represented by an animated line and a text box that give the usual visual clues to downloading progress.

A few noteworthy points about this picture:

  • The Properties palete is used to give the text a variable name. This means we can write script that alters its value. This is only possible with text created with the text field tool and not with the type tool.
  • Notice that the progressBar object has two Position keyframes. LM2 will animate the progress bar's position as downloading proceeds.
  • The labels "beginLoadLoop" and "endLoadLoop" are used in the preloader script at the 1 second keyframe script. Obviously the intention is that the preloader movieclip is looped between these labels.
  • The script at frame 1 initialtes the loading of the sound's movie clip as shown below.

Keyframe scripts

at frame 0

The downloading of the SWF file that contains the sound's movieclip - the one that we created right at the beginning of the tutorial- is initiated. We specify a level in the document stack higher than our own. Our player will be _level0 as it's intended to be used only in this way. We have chosen _level5 for the sound's movieclip.

loadMovieNum("GSClip.swf", 5);

at frame 1 sec: 00 f

At this point we take a snapshot of the current state of downloading. We can then use these figures to inform the user how we're doing. Also we can see whether we need to loop back or can end the preloading process.

var lFrames = _level5._root._framesloaded;
var tFrames = _level5._root._totalframes;
this.progress = ( Math.floor((lFrames / tFrames) * 100)) + "% loaded.";
if (lFrames == tFrames){
    this.gotoAndPlay("endLoadLoop");
}
else{
    this.gotoAndPlay("beginLoadLoop");
}

at frame 1 sec: 02 f

This is the script that will execute after the label "endLoadLoop" has been reached. In other words, when the preloader knows that the sound's movieclip is completely loaded.

_root.playButton.lmSetCurrentState("stopped");

Thats It!

 

Copyright © 2002 LiveMotionCentral.com, All Rights Reserved RESOURCES  |  NEWS  |  SUBMIT  |  ABOUT  |  HOME
LiveMotionCentral.com is in no way affiliated with Adobe Systems Incorporated

Adobe, After Effects, AlterCast, Atmosphere, Design Team, GoLive, Illustrator, LiveMotion, Photoshop and SVG Viewer are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries.
Visit Adobe Systems Incorporated to learn more.

Visit Adobe.com