Subscribe to Tutorial Feed

Flash and PHP Bible

The Flash and PHP Bible has been released! The book can be found on Amazon or wherever fine books are sold in your area.

The Flash and PHP Bible has a forum for quick support.

Scriptplayground » tutorials » as » Play Sound Samples From One File Using ActionScript 3

Play Sound Samples From One File Using ActionScript 3

Learn how to write a custom class to play portions of a single media file rather than loading an maintaining multiple files.

View an Example of this article before you get started.

As you start to develop applications more often you learn ways to save time. One common way to work with sound is to load in many clips and use whatever one you need at the time, or import them into the library during the authoring process. Both of these approaches work in most case, but do have limitations. For instance, loading the sound into the library means you can't update the sounds without republishing the entire movie. The second option, loading in the sounds at runtime works better but means some sort of loading manager is needed and takes longer.

Of course I wouldn't have written an article if there was only two ways to work with sound in ActionScript, because you probably already knew about those.

The third option for working with sound it to load in one sound file (mp3) and only play a portion of it, depending on which sound you want to play. As you noticed in the attached example, I have loaded a family guy sample where each button plays a certain portion of the sample. The idea of this approach is to minimize the loading process and make it easier to update.

For determing the specific point to play the file from I recommend using Soundbooth or a similar sound editor. In sounbooth it clearly displays the current time which makes it very easy to work with

Now that the background of this article is established, let's start by looking at how the custom class will be used and then move on to building the class. The first part of the code is your typical class import, which in this case is loading in the custom class. Then a variable is set to hold the music file that will be loaded. An event listener is used to give the button the click ability which plays the sound.

The special method that is found within the CLICK event handler is passing along the start and end positions which determines which sound to play.

import SoundSnippet;

var url:String = "stewies_new_laws.mp3";
var soundSnippet1:SoundSnippet = new SoundSnippet(url);

sample1MC.addEventListener(MouseEvent.CLICK, playSound1);

function playSound1(e:MouseEvent):void
{
	soundSnippet1.playSound(0, 700);
}

That is the complete block of code for using the custom Sound class, the next step is to write that class.

The SoundSnippet class is responsible for loading the sound at startup, playing a certain portion and keeping track of the timers to make all this happen. Here is a class skeleton which will give you a better idea of how the class is structured.

package  
{
	import flash.display.Sprite;
	import flash.events.*;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.net.URLRequest;
	import flash.utils.Timer;

	public class SoundSnippet 
	{
		...

		function SoundSnippet(url:String) {}

		public function playSound(start:uint=0, end:uint=0):void {}

		private function timerHandler(event:TimerEvent):void {}
		private function soundComplete():void {}
		private function ioErrorHandler(event:Event):void {}
		private function progressHandler(event:ProgressEvent):void {}
		
		private function enableTimer():void {}
		
	}
}

The first part is responsible for importing the required classes in order to load and play a sound. Then the other methods are used to handle the loading process and keep track of the timers to ensure the sound stops at the correct point.

The constructor function is used to load the sound and assign the proper event handlers. The url to load is passed in as an argument which is used to assign a brand new URLRequest instance.

function SoundSnippet(url:String)
{
	soundFactory = new Sound();
	soundFactory.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
	soundFactory.addEventListener(ProgressEvent.PROGRESS, progressHandler);
	
	var request:URLRequest = new URLRequest(url);
	soundFactory.load(request);
}

The next method to focus on is the playSound, this method is called when you want to start the sound. The start and ending points are passed in as separate arguments. If the end point is not passed in the sound clip is played to the end by pulling in the length of the sound file. The last step of this method is to make a call to enableTimer which initializes a timer.

public function playSound(start:uint=0, end:uint=0):void
{
	song = soundFactory.play(start);
	
	if(end == 0)
	{
		endPoint = soundFactory.length;
	}
	else
	{
		endPoint = end;
	}
			
	enableTimer();
}

The next method, enableTimer is called within the playSound method to initialize the Timer events.

private function enableTimer():void
{
	timer = new Timer(20);
	timer.addEventListener(TimerEvent.TIMER, timerHandler);
	timer.start();
}

The last of the special methods would be timerHandler which looks at the current duration and checks to make sure it is less than the ending point.

function timerHandler(event:TimerEvent):void 
{
	if(uint(song.position.toFixed(2)) >= endPoint)
	{
		timer.stop();
		song.stop();
				
		soundComplete();
				
		return;
	}
}

The other three methods are used to handle the loading and playing events.

private function soundComplete():void 
{
	trace("Snippet finished playing");
}
		
private function ioErrorHandler(event:Event):void 
{
	trace("ioErrorHandler: " + event);
}
		
private function progressHandler(event:ProgressEvent):void 
{
	trace("progressHandler: " + event);
}

You should now have all of the class completed and can test out the example. Make sure you have saved the MP3, class and FLA all in the same directory or edited the paths if you moved things around.

Here is the completed class for easy copy and pasting. Simply save the file as SoundSnippet.as in the same directory as the sound and Flash file (FLA).

package  
{
	import flash.display.Sprite;
	import flash.events.*;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.net.URLRequest;
	import flash.utils.Timer;	

	public class SoundSnippet 
	{
		
		private var song:SoundChannel;
		private var timer:Timer;
		private var soundFactory:Sound;
		
		private var endPoint:uint;
		
		function SoundSnippet(url:String)
		{
			soundFactory = new Sound();
			soundFactory.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			soundFactory.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			
			var request:URLRequest = new URLRequest(url);
			soundFactory.load(request);
		}

		public function playSound(start:uint=0, end:uint=0):void
		{
			song = soundFactory.play(start);
			
			if(end == 0)
			{
				endPoint = soundFactory.length;
			}
			else
			{
				endPoint = end;
			}
			
			enableTimer();
		}

		private function enableTimer():void
		{
			timer = new Timer(20);
			timer.addEventListener(TimerEvent.TIMER, timerHandler);
			timer.start();
		}

		function timerHandler(event:TimerEvent):void 
		{
			if(uint(song.position.toFixed(2)) >= endPoint)
			{
				timer.stop();
				song.stop();
				
				soundComplete();
				
				return;
			}
		}
		
		private function soundComplete():void 
		{
			trace("Snippet finished playing");
		}
		
		private function ioErrorHandler(event:Event):void 
		{
			trace("ioErrorHandler: " + event);
		}
		
		private function progressHandler(event:ProgressEvent):void 
		{
			trace("progressHandler: " + event);
		}
		
	}
}

If you're going to use this a lot in your site then it is best if you get some good managed hosting to make sure that it loads perfectly, specially if you have a huge amount of traffic.

For any questions or comments please feel free to post them in the comment form below.

Follow Scriptplayground on Twitter (@scriptplay)

Comments: Play Sound Samples From One File Using ActionScript 3

 megat afif  Tue Mar 18, 2008 11:24 pm  
i'm a newbie. could you write this code in full php script as example..thank
 mkeefe  Wed Mar 19, 2008 3:23 am  
The code is for ActionScript 3 (Flash 9) and is provided in full within the last block of code.

This really isn't a task for PHP as it runs on your server and not in the users browser.
 tom  Sat May 24, 2008 8:01 pm  
Thanks for the excellent class. I modified it slightly by making the sound loop...
 Wolfram  Mon Oct 6, 2008 6:45 am  
Hey,
thanks for this code, I've used it in the prototype app for my diploma thesis. Can you somehow post me your name to give reference to you?
 mkeefe  Mon Oct 6, 2008 7:52 am  
@ Wolfram - Glad to hear it was useful for you, and on something so important!.

Sure, my "title" is: "Matthew Keefe, Founder, mkeefeDESIGN"
 snivy  Fri Jan 23, 2009 8:19 pm  
Hi, I am looking for a similar solution to get multiple sound bites to play in a flash site. Just wanted to mention that if all 3 samples are activated the sounds play over top of one another. I am currently trying to solve this problem myself.
 Arthur  Wed Feb 4, 2009 10:26 am  
Beautiful, I'm looking to use a single audio file and create a "sound sprite", and this is perfect! Thank you sir.
 Kevin  Sat Oct 17, 2009 8:39 am  
snivy - add a stop action [ stop(); ] on each button press before the code that plays the new sound.
 Phil  Thu Nov 19, 2009 9:50 am  
Matthew - very clever approach. I'm a newbie to ActionScript and don't quite see the code connection to your example Menu Buttons to activate the different sound bites. Could you clarify? Many Thanks.
 mkeefe  Thu Nov 19, 2009 10:35 am  
@Phil - I don't explain how to create the specific example in this tutorial, but please feel free to contact me via matt(at)mkeefedesign(dot)com and i'll be sure to send the code over to you.
 Wayne  Thu Jan 14, 2010 9:52 am  
This is excellent example!

I use Adobe soundbooth to put markers on sound files. The markers are in an XML file with a name (marker1, marker2,...etc) and a time stamp to the milliseconds.

Is there a way to use the actionscript to play part of the sound file from marker to marker (by using the timestamp information) ?
 mkeefe  Wed Jan 20, 2010 6:19 am  
@Wayne - You can load the XML file, parse the marker data and store that in an object. Then you could use that to play certain portions of the audio track.
 Guest  Mon Sep 6, 2010 11:20 pm  
Hi,

This is very useful class.
I am making flash teaching materials which have a lot of buttons with sound attached. So far, we are cutting sounds in external software then import in Library.
One stuff espacially doing Audio editing actually.

But with your method, we do not need Audio editor.

My problem is:
Could you post a code for slitly different case:
We already have a sound file in Library.
So, what the code for it should looks like?

Kindly,
Tom
withlightspeed@gmail.com
 Nilay  Wed Oct 13, 2010 1:01 am  
This is exactly what I was looking for today!!!

Thanks a lot for sharing!

~Nilay
 virago 535  Sat Oct 16, 2010 4:04 am  
thanks to you
With your post I've found all the information I need to use sounds in AS 3
 Rob  Sun Oct 17, 2010 9:38 am  
I think what "megat afif" might be wanting is how you might call this script from PHP - say you have a db of 500 mp3's or so, and you want to show 10 per page, then by clicking a button next to each selection, you'd play a 30-sec sample or something - like Amazon does on their music pages...
 Nilay  Tue Oct 19, 2010 5:22 pm  
@mkeefe: I have one doubt.
I am dealing with sound snippets of upto 100 milliseconds, I have the correct start and end positions.

To get a better resolution, I have made the timer event delay to be 1millisecond.

But everytime I try to play a snippet of say 100~150 millisecond, the application will not play till the exact end point, it plays 30~70 milliseconds (this varies with different segments of sound) of extra sound. I am not able to get it working till its exact end points.
 Ziggurat  Tue Nov 2, 2010 2:16 am  
What is the best way to stop the clips from overlapping. In the example the sounds overlap if you click the buttons too early. I tried using stop(); at the start of the button click but it didn't work. Do you have any good ideas for a stop() function within the class?
 mkeefe  Tue Nov 2, 2010 7:52 am  
@Ziggurat - For that you would want to run the sound stop, stopAllSounds() or specifically the one channel that is playing. The function stop() is for stopping the playhead on the Flash timeline.
 Oleg  Thu Mar 31, 2011 5:26 pm  
Why did you use Timer(20)?
Would not it be easier to make it Timer(end-start,1)?
This way it would go off only once to stop your sound from playing further. Does it make sense?
 mkeefe  Mon Apr 4, 2011 1:30 pm  
@Oleg - The problem is Flash timing isn't perfect so in your example code if things got out of sync the Timer event would never fire. Its possible, just a caveat.
 Jazz  Mon May 30, 2011 9:27 am  
Great article. I'm busy crying at the apparently inability to do this in silverlight or xna or winphone7 ;___;
Add a comment
The ability to add new comments has been disabled in this archived version.

Loading
Main | Tutorials | Articles