Sound, Part 4: Volume Slider

This final demonstration builds on our encounter with the SoundChannel object, showing how to control the volume of a sound while it is playing, using a draggable MovieClip. Click and drag the red triangle in the window above. Note how the sound volume increases and decreases as you move up and down the scale. The text field shows the current volume level.

We'll first explain the graphical part (the draggable indicator), then the Sound resources.

I. Draggable slider

The triangular slider in this project exists in the main movie Library as a MovieClip called control_mc. It is linked to the class controlClass. This class handles both interactions and sound effects. We'll discuss the interactive aspect first.

We make the following imports to handle interactive behavior:

  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Rectangle;

The last of these imports introduces a package we haven't seen before -- flash.geom, and an unfamiliar object, Rectangle. You'll see how these come into play shortly.

Within the class body, where we declare variables, we start with this one:

  var boundRect:Rectangle = new Rectangle(8,8,0,200);

Any Rectangle object must be supplied with four Number arguments. The first pair define the top left corner of the rectangle, in terms of the X and Y axes of the stage. Our boundRect begins 8 pixels from the top and 8 pixels from the left boundary. The second pair indicate the width and height of the Rectangle. Ours is zero pixels wide and 200 pixels in height. While this is a pretty strange object, in terms of the plane geometry you learned in high school, it's acceptable for ActionScript. You'll see why we need that zero width setting presently.

Skipping over a number of items in the top of the class that relate to sound, we'll pass to the Constructor, where we find:

  addEventListener(MouseEvent.MOUSE_DOWN, dragOn);
  addEventListener(MouseEvent.MOUSE_UP, dragOff);

You'll be familiar with these listener/callback pairs from our previous work with draggable objects. One pair turns dragging on when the mouse goes down over our MovieClip; the other turns dragging off, when the mouse button is released.

The dragOff() callback is the standard sort of thing:

  function dragOff(event:MouseEvent):void
  {
    stopDrag();
  }

The dragOn() method, however, has an interesting feature:

  function dragOn(event:MouseEvent):void
  {
    startDrag(false, boundRect);
  }

The startDrag() method has two parameters here. The former is the Boolean that determines whether or not the MovieClip attaches to the mouse pointer at its registration point. (Remember that?) The latter is the Rectangle we defined above, boundRect. Passing this Rectangle as a parameter sets a bounding box for the slider. The slider can thus move only within a box -- actually, a line -- extending from 8,8 to 8,200. That's how we make sure our draggable object can move only in the Y axis.

So much for the visual effects; now on to the sound business, and how the position of the slider controls volume.

II. Sound

Take away the slider business, and the class controlClass looks very much like the simple soundBtnClass we outlined for our start/stop project. It begins with the same set of imports, plus one:

  import flash.net.URLRequest;
  import flash.media.Sound;
  import flash.media.SoundChannel;
  import flash.media.SoundTransform;

In addition to the SoundChannel object, which we need to handle interactive control, we also have a SoundTransform object. This is yet another auxiliary that works with SoundChannel and Sound, and we'll explain it in due course.

As you might expect, each of these imported objects gets a variable in the declarations section:

  //variables needed for Sound effects
  var soundReq:URLRequest = new URLRequest("TBL.mp3");
  var snd:Sound = new Sound();
  var sndChannel:SoundChannel = new SoundChannel();
  var sndTrans:SoundTransform;

We'll take as read here our note about having to use a fully-qualified URL as argument of the URLRequest object. For the sake of simplicity, we've shown the relative URL above.

And so we come back to the Constructor, which also contains some statements pertaining to sound:

  snd.load(soundReq);
  snd.addEventListener(Event.COMPLETE, soundGood);

These lines should require no explanation at this point; they're been present in every one of our Sound projects so far.

Here's a statement that might be of slightly greater interest:

  addEventListener(Event.ENTER_FRAME, volCheck);

As you can probably guess, this listener/callback pair handles the volume setting; we use the ENTER_FRAME event so that we can adjust the volume on frame entry, many times per second.

Here's the other half of the mechanism (i.e., the callback method):

  function volCheck(event:Event):void
  {
    //volume control
    sndTrans = new SoundTransform(y/200);
    sndChannel.soundTransform = sndTrans;
  }

We instantiate a new SoundTransform object in the variable sndTrans, passing it a specific Number value, y/200. So what's that about?

Well, the variable (or property) y reports the current vertical location of the present MovieClip (we could have said this.y), which is to say, how far up or down the slider sits within its 200-pixel range. Dividing this value by 200 gives us a value between 0 and 1. It just so happens that volume for Sound objects (expressed in SoundTransform) is calibrated between 0 (silent) and 1 (full volume). So as we move the slider toward the bottom of the screen, increasing the value of y, our sound grows louder; and as we move toward the top, it fades down.

All that's necessary to complete this transaction is to add the second statement above, which sets the soundTransform property of our SoundChannel (sndChannel) to our SoundTransform object, sndTrans.

Complicated, yes. Why do we need to pass the SoundTransform object to the SoundChannel, and not directly to the Sound object? So many questions, Grasshopper. Perhaps you will think this is BECAUSE SOME SOFTWARE ENGINEERS SIMPLY CAN'T DO ANYTHING SIMPLY. Strange are the ways of code.

The only piece of this class we haven't discussed is the callback method soundGood(), which is nothing very special:

  function soundGood(event:Event):void
  {
    sndChannel = snd.play(0,1000);
  }	

Just remember that we have to use the SoundChannel object, because we're doing something interactive. We're using a 1000-iteration loop here, though you could easily choose a different value.

III. Source files

Source files and sound resources for this project are available in the folder soundSlider, within soundDemos in the shared account on student-iat. To work with these files on your own system, download the MP3 file TBL.mp3.



University of Baltimore Logo

Last updated: 06/24/08 16:26:20
Copyright © 2008 School of Information Arts and Technologies