DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 13.6 Setting In and Out Points

13.6.1 Problem

You want to play a sound with start and stop (in and out) points other than the beginning or end of the sound.

13.6.2 Solution

Create and invoke a custom play( ) method.

13.6.3 Discussion

The start( ) method plays and optionally loops a sound with a configurable starting offset. You can define a custom method that also allows you to stop the sound after an elapsed period of time. We can achieve this by using an empty movie clip to poll the sound's elapsed time and telling Flash to stop the sound when the maximum time is exceeded.

Our custom play( ) method works with Sound objects created using the custom createNewSound( ) method from Recipe 13.1. If you don't want to use the createNewSound( ) method, you must create an empty movie clip and store a reference to that movie clip in a property named mc within the Sound object (createNewSound( ) does this automatically).

Here is our custom play( ) method, which accepts up to three parameters: the starting offset (in seconds), the number of loops, and the maximum playing time (in milliseconds). We'll also define another method that allows us to add a callback function that is invoked when the sound stops. Make sure you add these methods to your Sound.as file for easy inclusion in other projects.

Sound.prototype.play = function (startOffset, loops, maxTime) {

  // Call the start(  ) method with the values for offset and loops.
  this.start(startOffset, loops);

  // If maxTime is undefined, then don't do anything else.
  if (maxTime == undefined) {
    return;
  }
  // Otherwise, we have to detect the elapsed playing time. Record the time when the
  // sound started.
  var startTime = getTimer(  );

  // Use an interval to monitor the sound by calling the custom monitorPlayback 
  // method every 100 ms. Pass the method the values for startTime and maxTime.
  this.monitorPlaybackInterval = setInterval(this, "monitorPlayback",
                                 100, startTime, maxTime);
};

// Here is the function invoked at each interval.
Sound.prototype.monitorPlayback = function (startTime, maxTime) {

  // If the elapsed time exceeds the maxTime, stop the sound, clear the interval, and
  // invoke the callback function.
  if (getTimer(  ) - startTime >= maxTime) {
    this.stop(  );
    clearInterval(this.monitorPlaybackInterval);
    this.onStopPath[this.onStopCB](  );
  }
};

// The setOnStop(  ) method allows you to define a callback function to invoke when the
// sound stops. The parameters are a string specifying the function name and an
// optional path to the function. If path is undefined, the Sound object's parent 
// property is used instead. The parent property is defined only if you use the
// custom createNewSound(  ) method to create the sound.
Sound.prototype.setOnStop = function (functionName, path) {
  this.onStopPath = (path == undefined) ? this.parent : path;
  this.onStopCB = functionName;
};

Here is an example of how to use the play( ) method:

#include "Sound.as"

// Create the sound.
mySound_sound = Sound.createNewSound(  );

// Attach a sound from the Library. Alternatively, you can load the sound from an
// external source (see Recipe 15.5).
mySound_sound.attachSound("MySoundSymbol");

// Define a callback function.
function onSoundStop (  ) {
  trace("Sound has stopped.");
}

// Play the sound from the beginning. Loop it (up to) six times and stop the sound
// after 15 seconds.
mySound_sound.play(0, 6, 15000);

// Set the callback function.
mySound_sound.setOnStop("onSoundStop");

Note that the starting offset is measured in seconds, but the maximum playing time is measured in milliseconds (and the timing is accurate only to within about 100 milliseconds). You can modify the play( ) method to use seconds or milliseconds for both values. Also note that the play( ) method does not check the current time of the sound. Instead, it tracks the total amount of time that the sound has been playing. Depending on the duration of the sound and the specified inputs, the sound may not complete, or it may loop multiple times before the maximum elapsed time is reached. In either case, maxTime is not a true out point, but simply an elapsed time limit.

Here is a modified version, playToPoint( ), that accepts a true out point as the third parameter. The out point is relative to the sound's beginning, in milliseconds, regardless of the starting offset. Add the following code to your Sound.as file for easy inclusion in other projects:

Sound.prototype.playToPoint = function (startOffset, loops, outPoint) {
  // If loops is invalid, play the sound once from startOffset to outPoint.
  if (loops <= 1) {
    loops = 1;
  }
  // Store the input parameters in object properties of the same name.
  this.loops = loops;
  this.startOffset = startOffset;

  // If outPoint is undefined or 0, then just play the sound as usual.
  if (outPoint == undefined || outPoint == 0) {
    // Call the start(  ) method with the values for startOffset and loops.
    this.start(startOffset, loops);
    return;
  }

  // Call the start(  ) method with a starting offset (startOffset) only. 
  // We'll manually loop the sound the specified number of times 
  // from within onSoundComplete(  ), each time restarting the sound 
  // at startOffset once it reaches outPoint.
  this.start(startOffset);

  // Initialize the loopCount to 0.
  this.loopCount = 0;

  // Use onSoundComplete(  ) to catch when the sound completes after each loop if the
  // specified outPoint happens to be past the duration of the sound.
  this.onSoundComplete = function (  ) {
    this.loopCount++;
    if (this.loopCount < this.loops) {
      this.start(this.startOffSet);
    }
  };

  // Monitor the sound status every 50 ms and pass the interval callback method the
  // values for startOffset, loops, and outPoint.
  this.monitorOutpointInterval = setInterval(this, "monitorOutpoint",
                                 50, startOffset, loops, outPoint);
};

// Here is the function invoked at each interval.
Sound.prototype.monitorOutpoint = function (startOffset, loops, outPoint) {

  // If the sound's current time exceeds the outPoint, stop the sound and increment
  // the loopCount.
  if (this.position >= outPoint) {
    this.stop(  );
    this.loopCount++;

    // If the total number of loops is reached, stop the sound, clear the interval,
    // and invoke the callback function.
    if (this.loopCount > loops) {
      this.stop(  );
      clearInterval(this.monitorOutpointInterval);
      this.onStopPath[this.onStopCB](  );
    } else {
       // Otherwise, restart the sound from startOffset and wait for it to reach
       // outPoint again.
       this.start(startOffset);
    }
  }
};

// Our setOnStop(  ) method, which defines a callback function to invoke when the sound
// stops, is the same as in the previous example.
Sound.prototype.setOnStop = function (functionName, path) {
  this.onStopPath = (path == undefined) ? this.parent : path;
  this.onStopCB = functionName;
};

Here is an example of how to use the playToPoint( ) method:

#include "Sound.as"

// Create the sound.
mySound_sound = Sound.createNewSound(  );

// Attach a sound from the Library.
mySound_sound.attachSound("MySoundSymbol");

// Define a callback function.
function onSoundStop (  ) {
  trace("Sound has stopped.");
}

// Play the sound from two seconds in. Loop it three times and stop the sound each
// time it reaches the out point six seconds into the sound.
mySound_sound.play(2, 3, 6000);

// Set the callback function.
mySound_sound.setOnStop("onSoundStop");
    [ Team LiB ] Previous Section Next Section