Hack 60 A Custom Sound Transform Class 
Create a custom class to perform sound fades
and cross-fades.
You'll often want to
perform sound fades or cross-fades (fading in one sound while fading
out another). The common nature of the task suggests that it is a
great candidate to be implemented as a custom class. The class can
take care of all the grunt work, allowing us to perform a sound fade
using a few simple calls to the custom class's
methods.
Like the built-in Color class, the
Sound class supports a setTransform(
)
method. Earlier, we created a custom color transform class [Hack #10] and we can apply the same
concepts to create a similar custom class for sound.
We've chosen to implement the
SoundTrans class as a subclass of the built-in
Sound class. The custom subclass contains two
methods:
- SoundTrans.fadeIn(duration, loop)
-
Starts a sound and fades it in from 0% to 100% volume over
duration milliseconds and plays it
loop times
- SoundTrans.fadeOut(duration)
-
Fades a sound to zero volume over duration
milliseconds
Here is our object-oriented version, implemented as a custom
SoundTrans class, which must be stored in an
external SoundTrans.as file:
// This ActionScript 2.0 code must go in an external SoundTrans.as file
class SoundTrans extends Sound {
// FADE_OUT fades out a sound.
// FADE_IN fades in a sound.
// RATE sets the rate the effects will run at, in ms.
private static var FADE_OUT:Object = {ll:0, lr:0, rr:0, rl:0};
private static var FADE_IN:Object = {ll:100, lr:0, rr:100, rl:0};
private static var RATE:Number = 60;
private var interval:Number;
private var startTime:Number;
// (Re)starts the sound and fades it in over duration ms
// then loops the sound loop times.
public function fadeIn(duration:Number, loop:Number):Void {
// Invoke functions inherited from the Sound superclass.
stop( );
start(0, loop);
setTransform(FADE_OUT);
// Invoke a custom method defined for the subclass.
applyTransform(FADE_IN, duration);
}
// Fades out the sound over duration ms,
// stopping the sound at the end.
public function fadeOut(duration:Number):Void {
applyTransform(FADE_OUT, duration);
}
// Initiate a fade and set up an interval to complete it over time.
private function applyTransform(transObject:Object,
duration:Number):Void {
// Get the current sound transform object.
var getTrans:Object = getTransform( );
var diffTrans:Object = new Object( );
if (duration < RATE) {
duration = RATE;
}
startTime = getTimer( );
for (var i in transObject) {
diffTrans[i] = (transObject[i]-getTrans[i]) / (duration/RATE);
}
// First parameter is current object, this.
// Second parameter is function to invoke (transition( )).
// Third parameter is interval duration in ms.
// Fourth, fifth, and sixth parameters get passed to transition( ).
interval = setInterval(this, "transition", RATE, transObject, diffTrans,
duration);
}
private function transition(transObject:Object, diffTrans:Object,
duration:Number):Void {
var getTrans:Object = getTransform( );
for (var i in diffTrans) {
getTrans[i] += diffTrans[i];
}
setTransform(getTrans);
if (getTimer( ) - startTime > duration) {
// Cleanup
setTransform(transObject);
clearInterval(interval);
}
updateAfterEvent( );
}
}
Note that our class doesn't add new methods directly
to the Sound class (as was typical when using
prototype-based inheritance in ActionScript 1.0). Instead, the
SoundTrans class extends (i.e., subclasses) the
built-in Sound class. This has the advantage of
keeping the new sound functionality (in our
SoundTrans class) separate from the existing
Sound class, while at the same time working
seamlessly with the Sound class.
You can see this in the following code example, which demonstrates
how to use the SoundTrans class.
First, create an instance of the SoundTrans
class. This code creates a SoundTrans object
that uses the groovyLoop.wav file (which is
presumed to be available in the Library with sound linkage identifier
groovyLoop).
var groovy:SoundTrans = new SoundTrans(this);
groovy.attachSound("groovyLoop");
We can now use the methods of the SoundTrans
class (or those of the Sound superclass) with
our SoundTrans instance. The following causes
the sound to start playing with the sound volume fading in from zero
to 100% over three seconds. The sound then loops twice:
groovyTrans.fadeIn(3000, 2);
The following fades out the sound over six seconds:
groovyTrans.fadeOut(6000);
Consider enhancing this custom class to implement additional
features, such as:
Making the RATE value user-definable. Adding a method that can accept an array of fade points, allowing you
to create a scripted version of the sound envelope.
|