The basics of working with sound in Flex3


My previous article “  Understanding Embedding Assets in Flex3” made a flight on 5000 feet to show the big picture of concepts related to Flex3 and assets manipulation . Now lets get a bit lower and focus on the subject of how flex handles sound .

Before you can control a sound in ActionScript, you need to have the sound information loaded into Flash Player or AIR. There are four ways you can get audio data into Flash Player or AIR so that you can work with it using ActionScript.

  • You can load at runtime an external sound file such as an mp3 file into the SWF;
  • You can embed the sound information into the SWF file directly when it’s being created;
  • You can get audio input using a microphone attached to a user’s computer,
  • And you can access sound data that’s streamed from a server.

Seven main classes are associated directly with sound :

  1. Sound : Makes it possible to create a Sound object to load , control  and access metadata from the MP3 file you are loading
  2. SoundChannel : Allows you to treat each sound you load as a separate channel, so you can control the sound , get /set its playhead position , and assign a SoundTransform object
  3. SoundLoaderContext : Provides contextual information for the Sound class at load time.
  4. SoundTransform : Allows you to control the volume and panning of your loaded sound .
  5. SoundMixer : Provides globas sound control .
  6. ID3Info : Contains properties that reflect ID3 metadata .
  7. Microphone : Lets you capture audio from a microphone to the computer that is running Flash Player

The following picture demonstrates the cooperation of these classes

There are some other Classes without which we couldn’t use sound , such as the URLRequest class , which we use to load the sound file . But let us concentrate  on the direct sound Classes.

The software used and selections made when encoding an MP3 file for use with Flex can make all the difference when it comes to executing a project. First, when creating a MP3 file for use with Flex, you must ensure that it is encoded with 44kHz or 11kHz sample rate. Flex cannot load in a file encoded at 24kHz or 16kHz. The bits/sec do not matter for compatibility, but the sample rate does. Also, if you are going to be attempting to loop the MP3 file, you will want to find an encoder that DOES NOT add any space at the end of the file. Space at the beginning can be mitigated with offset start playing, but space at the end can be a killer.
Simple Loading an MP3 at run time (IDE or Flex)

The first example is the simplest way to load an external sound at run-time. It doesn’t wait for the sound to be loaded before it is played, and simply assumes they sound is available.MP3 loads into Flash Player as a progressive download , that means that as soon enuf of the audio has downloaded into the player it will begin to playback

01 //Actionscript code
02 import flash.media.Sound;
03 import flash.media.SounChannel ;
04 import flash.net.URLRequest;
05
06 private var mySound:Sound ;
07 private var sndChannel:SoundChannel = new SoundChannel ;
08
09 var request:URLRequest = new URLRequest("assets/extSound.mp3");
10 mySound = new Sound(request);
11 sndChannel = mySound.play();

In the above example, you must first create a new URLRequest and give it the the location of the file to load. You then need to create Sound object to hold that loaded sound, and lastly, to play the sound, you must add it to a SoundChannel object when calling the Sound.Play() method. That’s pretty much it for a simple sound load and play.

Monitoring the load of an MP3 and then Playing the Sound (IDE or Flex)

A Sound object dispatches a number of different events during the sound loading process. Your application can listen for these events to track loading progress and make sure that the sound loads completely before playing. The following table lists the events that can be dispatched by a Sound object .

Event Description
open (Event.OPEN) Dispatched right before the sound loading operation begins.
progress (ProgressEvent.PROGRESS) Dispatched periodically during the sound loading process when data is received from the file or stream.
id3 (Event.ID3) Dispatched when ID3 data is available for an mp3 sound.
complete (Event.COMPLETE) Dispatched when all of the sound resource’s data has been loaded.
ioError (IOErrorEvent.IO_ERROR) Dispatched when a sound file cannot be located or when the loading process is interrupted before all sound data can be received.
The following example code have added 2 event listeners to aid in monitoring the load progress of the file and have also added a function called playSound():void that will be called when the file has been completely loaded in. There is no onComplete event that fires when the sound has been loaded, so we must check the sndProgressHandler
method until the sound has been loaded, and then we call the playSound():void method. The snderrorHandler method would be called if there was some type of security access violation or a file not found error.
01 //Actionscript code
02 <mx:Script>
03         <!--[<span class="hiddenSpellError" pre="">CDATA</span>[-->
04     import flash.net.URLRequest;
05     import flash.events.ProgressEvent;
06     import flash.events.IOErrorEvent;
07     import flash.media.Sound;
08         import flash.media.SoundChannel ;
09
10     private var sndChannel:SoundChannel = new SoundChannel();
11     private var snd:Sound;
12     private function init():void {
13
14  var sndUrl:URLRequest = new URLRequest("assets/sound2.mp3");
15  snd = new Sound(sndUrl);
16
17 snd.addEventListener(IOErrorEvent.IO_ERROR, snderrorHandler);
18 snd.addEventListener(ProgressEvent.PROGRESS, sndprogressHandler);
19
20  }
21
22     private function sndprogressHandler(e:ProgressEvent):void {
23         if (e.bytesLoaded >= e.bytesTotal) {
24             playSound();
25         }
26      }
27
28     private function snderrorHandler(e:IOErrorEvent):void {
29          trace("sound load error " +  e.text);
30       }
31
32     private function playSound():void {
33          sndChannel = snd.play();
34       }
35
36         ]]>
37     </mx:Script>
Simple Embedding of an MP3 at compile time (Flex Only)

A Simple embed of a sound in a Flex app is quite easy . It is very similar to the simple load of an MP3, but even easier. Once the [Embed] is called, you must declare a class for the file directly underneath. You use this class name when you instantiate your Sound object and use the “as” construct to cast the generic loaded asset as a Sound. You then can play the sound in the exact same manner you would if it was loaded in, by assigning it to a sound channel.

01 < ? x m l version="1.0" encoding="utf-8"?>
02 <mx:Application xmlns:mx="http://www.adobe.com /2006/mxml" >
03 <mx:Script>
04
05        [Bindable]
06             [Embed('assets/sound1.mp3')]
07             private var sndCls:Class;21
08
09     public var snd:Sound = new sndCls() as Sound;
10     public var sndChannel:SoundChannel;
11
12     private function playSound():void {
13         sndChannel = snd.play();
14             }
15
16     </mx:Script>
17
18     <mx:Button label="Play sound" click="playSound()" />
19         </mx:Application>

Until now the loaded at runtime , or embeded sound played ones until the end , and stoped . If we need to loop through , pause , stop , resuming , reading metadata of the sound (ID3-data) and / or adjusting the volume of the sound , we have to enrich our code with more functionality . Let see how it can be done .

Simple Seamless Looping the play of a loaded or embedded .mp3 file (IDE or Flex)
You can easily loop the play of an MP3 by calling play() and passing in an offset and a number of loops. The offset is critically important here, because if you were able to encode your MP3 file with an encoder that doesn’t put and “follower” space at the end of the file, you will be able to simply play with the offset number of milliseconds until the file loops seamlessly. For the example above, I changed the play() to look like this:
1 sndChannel = snd.play(956,5);
That tells the SoundChannel to play the loop 5 times and always start 956 milliseconds into the file on every loop.The second parameter is the number of times to loop. Set it to zero to play the sound one time. There’s no real way (that I have found) to play the audio infinite times, so I put in int.MAX_VALUE which is a 32-bit signed integer of the value 2,147,483,647. Sure this won’t loop forever, but given a one second audio clip it would loop for about 68 years!
1 sndChannel = snd.play(956,int.MAX_VALUE);

Stopping , pausing and resuming the mp3 sound file

The SoundChannel class (flash.media.SoundChannel ) controls a sound in an application . Each sound playing is assigned to a sound channel , and the application can have multiple sound channels that are mixed together .The SoundChannel class contains a stop() method , properties for monitoring the amplitude (volume) of the channel , and a property for setting a SoundTransform object to the channel .There is no  actual pause functionality in the Sound class , nor in any other sound-related classes . You therefore need to use a simple hack . Because you will need to stop the sound playing to make it appear that it is paused , you will need to use the play() command to start it again . But you want to play from the point where the user clicked the pause button the first time, right ? And simply playing it again will just start the sound file from the beginning . Luckily , the SoundChannel class has a property called position , which you can use to get the position of the playhead when the pause button is clicked the first time . You store the position before calling the SoundChannel.stop() method , and then use that as an offset when the pause button is clicked again , and restart playing from this offset . So let’s see all this functionality to work …
01 < ? x m l version="1.0" encoding="utf-8"?>
02 <mx:Application xmlns:mx="http://www.adobe.com /2006/mxml" >
03 <mx:Script>
04         <!--[<span class="hiddenSpellError" pre="">CDATA</span>[-->
05     import flash.net.URLRequest;
06     import flash.events.ProgressEvent;
07     import flash.events.IOErrorEvent;
08     import flash.media.Sound;
09     import flash.events.MouseEvent;
10
11     private var sndChannel:SoundChannel = new SoundChannel();
12     private var snd:Sound;
13     private var resumetime:Number = 0 ;
14
15     private function init():void {
16
17  var sndUrl:URLRequest = new URLRequest("assets/sound2.mp3");
18  snd = new Sound(sndUrl);
19
20 snd.addEventListener(IOErrorEvent.IO_ERROR, snderrorHandler);
21 snd.addEventListener(ProgressEvent.PROGRESS, sndprogressHandler);
22
23  }
24
25     private function sndprogressHandler(e:ProgressEvent):void {
26         if (e.bytesLoaded >= (e.bytesTotal /3 )) {
27           //  playSound();
28           playButton.enabled = true ;
29         }
30      }
31
32     private function snderrorHandler(e:IOErrorEvent):void {
33          trace("sound load error " +  e.text);
34       }
35
36     private function playSound(evt:MouseEvent):void {
37          sndChannel = snd.play(resumetime ,int.MAX_VALUE);
38          stopButton.enabled = true ;
39          playButton.enabled = false;
40       }
41
42     private function stopSound(evt:MouseEvent):void {
43         resumetime = sndChannel.position;
44         sndChannel.stop();
45         stopButton.enabled = false ;
46         playButton.enabled = true ;
47       }
48
49         ]]>
50     </mx:Script>
51
52     <mx:Label text="The basics of working with sound in Flex3t "  color="red"/>
53
54     <mx:Button id="playButton" label="Play sound" click="playSound(event)"  enabled="false"/>
55     <mx:Button id="stopButton" label="Stop sound" click="stopSound(event)" enabled="false"/>
56
57 </mx:Application>

Working with sound metadata (ID3 data) :

ID3 is a specification for storing metadata about an mp3-file .Sound files that use the mp3 format can contain additional data about the sound in the form of ID3 tags.Not every mp3 file contains ID3 metadata. When a Sound object loads an mp3 sound file, it dispatches an Event.ID3 event if the sound file contains ID3 metadata. To prevent run-time errors, your application should wait to receive the Event.ID3 event before accessing the Sound.id3 property for a loaded sound.

The following table list the standard ID3 2.0 tags and the type of content the tags represent. The Sound.id3 property provides access to these tags through the format my_sound.id3.comment, my_sound.id3.album , and so on.

ID3 2.0 tag Corresponding Sound class property
COMM Sound.id3.comment
TALB Sound.id3.album
TCON Sound.id3.genre
TIT2 Sound.id3.songName
TPE1 Sound.id3.artist
TRCK Sound.id3.track
TYER Sound.id3.year

The following code shows how to recognize when the ID3 metadata for a sound file has been loaded , the code focused only on the part related to ID3 handling :

1 snd.addEventListener(Event.ID3, onID3InfoReceived);
2 function onID3InfoReceived(event:Event) {
3     var id3:ID3Info = event.target.id3;
4
5     trace("Received ID3 Info:");
6     for (var propName:String in id3)   {
7         trace(propName + " = " + id3[propName]);
8     }
9 }

Controling the volume of the sound :

The soundTransform class (flash.media.SoundTransform) allows control of volume and panning. Microphone , NetStream , SimpleButton , SoundChannel , SoundMixer , and Sprite objects all contain a  “soundTransform”  property , the value of which is a SoundTransform object . The most important property that we need to control the sound is …….. “volume”.

To control the volume of the sound , pass the SoundTransform object to the SoundChannel . We create a new SoundTransform object with the desired values and pass it to the SoundChannel that is currently playing .

The following code shows how to control the volume of the  sound file  , the code focused only on the part related to volume control .

01 <mx:Script>
02 import flash.media.SoundTransform;
03 private var adjVol:SoundTransform ;
04
05 private function volumeControl():void {
06          adjVol = new SoundTransform(volumectl.value);
07        //sndChannel is the sound object
08         sndChannel.soundTransform = adjVol ;
09       }
10 <mx:Script>
11
12 <mx:HSlider id="volumectl" change="volumeControl()" />

Copy from source tournasdimitrios1.wordpress.com/2010/09/02/the-basics-of-working-with-sound-in-flex3/

Advertisements
By dbglory Posted in Flex

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s