I need someone who is well versed in wordpress and customization of wordpress to make some changes to my already existing wordpress theme. Deadline – 3 days. Bid above $40 will be ignored. Only bid, if you can communicate well… (Budget: $30-250, Jobs: .NET, HTML, Java, PHP, WordPress)
flash, action script,html,css graphic designer needed by mojojive
I am looking for a professional flash,actionscript program who has experience with graphic design. I am looking to have a homepage made, from an already made template. You must also have a VERY VERY GOOD WORKING EXPERIENCE IN AFTER EFFECTS… (Budget: $750-1500, Jobs: Graphic Design, HTML5, Javascript)
Ebay sales, I ship first!!! by afrostmail
Are you good at ebay sales? have a feedback with over 100 feedback? US based? I can ship first to all your buyers and you will pay me only if they are satisfied. How does that sound? I sell fast moving goods, you can expect to make good money if you know what you are doing… (Budget: $250-750, Jobs: eBay)
YouTube TV Shows Uploading by zomer86
Logo Redesign by ADMAXCAT
Re-design Website by mesha2009
Thirty Ultra Spun Articles-Pay $5 Each- One each day by SeattleCo
Read this entire post or your will not be considered. 1. We need thirty articles written with perfect English grammar. 2. Each articles need to be 500 words and broken down into 5 unique paragraphs… (Budget: $30-250, Jobs: Academic Writing, Article Rewriting, Articles, Report Writing, Technical Writing)
Photoshop guru needed by kylieprobids
School Website Designing by mesha2009
Article Spinning, Rewriting articles with sinner syntax by alanx13
SEO quality content writer needed, Health, omega 3. by gilad27
I’m looking for long term quality content writer. i will need at least 100 articles or more written every month. about health and maybe other niches. you have to have a writing style, to be able to make emotional connection with the reader, so it doesn’t look like promotion … (Budget: $30-250, Jobs: Articles, Blog, Health, Internet Marketing, SEO)
Yahoo Accounts by PetkovskiB
Dear Freelancers! Our team provides yahoo mail accounts, if anyone is interested in buying, this is the right place. Payment is done only with GAF and it will have space to negotiate. Plus we have some great facebook scripts if anyone is interested as well… (Budget: $30-250, Jobs: Anything Goes, eCommerce, Facebook, Javascript, Social Engine)
Get search module working properly in Joomla by pixeldesignhouse
Need High Quality Video by extremeseo2020
Managing Sounds with Commands
Sound management is very important for many types of Flash applications, such as interactive websites and games. As long as you want to deliver a rich interactive experience, you might want to consider making use of sound effects and background music. In this tutorial, I’ll present a minimalistic sound management framework that manages sounds into sound tracks. And I’ll show how to integrate the sound framework with the command framework from my previous tutorials.
Introduction
I’ve played games with incautious sound management, and that degrades user experience. Have you ever played a game, say, an action game, where the character’s exclamation voice plays before the previous voice ends, overlapping each other? That’s a result of bad sound management: there shouldn’t be more than one voice of the same character playing at a time. The sound management framework I’m about to cover will take care of this issue by managing sounds with sound tracks.
The examples in this tutorial make use of the command framework and scene management framework from my previous tutorial, Thinking in Commands (Part 1, Part 2), and the examples also use the data manager class from Loading Data with Commands. I highly recommend that you go through these tutorials first before going on. Also, you’ll need the GreenSock Tweening Platform to complete the examples.
Step 1: Theory Sound Tracks
The sound track we’re talking about here has nothing to do with game or movie sound tracks. A sound track is an imaginary “track” associated with a playback of a single sound. One single sound track does not allow more than one sound playing at a time. If a sound track is currently playing a sound, we say it’s occupied. If another sound is to be played on an occupied sound track, the currently playing sound is stopped, and then the new one is played on the track. It is thus reasonable to play a single character’s voices on a single sound track, so as to avoid the sound overlapping issue mentioned earlier. Also, in most cases, there should be only one track for background music.
Let’s take a look at some conceptual figures. A single application can have multiple sound tracks.
Each sound track can hold one single playing sound.
If a sound is to be played on an occupied track, the “old” sound is first stopped, and then the “new” sound is played on the track.
Step 2: Theory The Framework
The Sound Management framework consistes of two classes, the SoundManager class and the SoundTrack class. Each sound track is assigned a unique key string. An occupied sound track’s underlying playing sound is actually a native SoundChannel object obtained from the native Sound.play() method, and the SoundManager class manages sound tracks and organizes the playback of sounds.
Here are some quick previews of the usage of the framework. The following code plays a new sound on a sound track associated with the key string “music”, where MySound is a sound class from the library.
//play a sound on the "music" track SoundManager.play("music", new MySound());
If the same line of code is executed again before the playback is finished, the original sound is stopped, and a new sound is played on the “music” track.
//stop the original sound on the "music" track and play a new one SoundManager.play("music", new MySound());
The SoundManager.stop() method stops a sound track associated with a specified key string.
//stop the "music" sound track SoundManager.stop("music");
In order to transform the sound, like to adjust the volume, we’ll need to obtain a reference to a sound track’s underlying sound channel. The reference can be obtained by accessing the SoundTrack.channel property.
var channel:SoundChannel = SoundManager.getSoundTrack("music").channel; var transform:SoundTransform = channel.soundTransform; transform.volume = 0.5; channel.soundTransform = transform;
Step 3: Classes The SoundTrack Class
Enough theory. Let’s get down to the coding. We are going to use different key strings to distinguish different sound tracks. Here’s the SoundTrack class, which essentially represents a key-channel pair. Details are described in comments.
package sounds { import flash.media.SoundChannel; /** * A sound track represents a key-channel pair. */ public class SoundTrack{ //read-only key value private var _key:String; public function get key():String { return _key; } //read-only sound channel reference private var _channel:SoundChannel; public function get channel():SoundChannel { return _channel; } public function SoundTrack(key:String, channel:SoundChannel) { _key = key; _channel = channel; } /** * Stops the underlying sound channel. */ public function stop():void { _channel.stop(); } } }
Step 4: Classes The SoundManager Class
And here’s the SoundManager class. Note that the key-track association is handled by using the Dictionary class. A track is emptied automatically if a playing sound has reached its end.
package sounds { import flash.events.Event; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundTransform; import flash.utils.Dictionary; /** * This class allows you to manage sounds in terms of sound tracks. */ public class SoundManager{ //a dictionary that keeps tracks of all sound tracks private static var _soundTracks:Dictionary = new Dictionary(); //a dictionary that maps a sound channel to its corresponding key for playback completion handling private static var _soundKeys:Dictionary = new Dictionary(); /** * Plays a sound and returns a corresponding sound track object. */ public static function play(key:String, sound:Sound, startTime:int = 0, loops:int = 0, transform:SoundTransform = null):SoundTrack { //if the sound track is occupied, stop the current sound track if (isPlaying(key)) stop(key); //play the sound, creating a new sound channel var channel:SoundChannel = sound.play(startTime, loops, transform); //listen for the complete event of the sound channel channel.addEventListener(Event.SOUND_COMPLETE, onSoundComplete); //create a new sound track var soundTrack:SoundTrack = new SoundTrack(key, channel); //add the sound track to the dictionary _soundTracks[key] = soundTrack; //add the channel-key mapping relation _soundKeys[channel] = key; return soundTrack; } /** * Returns a reference to the sound track corresponding to the provided key string. */ public static function getSoundTrack(key:String):SoundTrack { return _soundTracks[key]; } /** * Determines if a sound track is currently playing. */ public static function isPlaying(key:String):Boolean { return Boolean(_soundTracks[key]); } /** * Stops a sound track. */ public static function stop(key:String):void { var soundTrack:SoundTrack = _soundTracks[key]; //check if the sound track exists if (soundTrack) { //stop the sound track soundTrack.stop(); //and remove it from the dictionary delete _soundTracks[key]; //along with the channel-key relation delete _soundKeys[soundTrack.channel]; } } /** * Removes a sound track when the sound playback is complete */ private static function onSoundComplete(e:Event):void { //cast the event dispatcher to a sound channel object var channel:SoundChannel = SoundChannel(e.target); //remove the event listener channel.removeEventListener(Event.SOUND_COMPLETE, onSoundComplete); //extract the corresponding key var key:String = _soundKeys[channel]; //remove the sound track stop(key); } } }
Step 5: Example Sound Manager Testdrive
Now let’s test our sound management framework. We’re going to compare the outcome of repeated requests to play a sound with and without using the sound manager.
Step 6: Example New Flash Document
Create a new Flash document (duh).
Step 7: Example Create Buttons
Create two buttons on the stage. You can draw your own and convert them to symbols, or you can, as in my case, drag two Button components from the Components panel. Name them “boing_btn” and “managedBoing_btn”.
Step 8: Example Import the Sound
Import the sound we’re going to play to the library. You can find the “Boing.wav” file in the example source folder.
Step 9: Example The Document Class
Finally, create an AS file for the document class. The code is rather straightforward, so I just explain everything in the comments.
package { import flash.display.Sprite; import flash.events.MouseEvent; import flash.media.Sound; import sounds.SoundManager; public class BoingPlayer extends Sprite { public function BoingPlayer() { //add the click listeners for both buttons boing_btn.addEventListener(MouseEvent.CLICK, onBoing); managedBoing_btn.addEventListener(MouseEvent.CLICK, onManagedBoing); } //play the sound directly by invoking the Sound.play() method. private function onBoing(e:MouseEvent):void { var sound:Sound = new Boing(); sound.play(); } //play the sound with the sound manager on the "boing" sound track private function onManagedBoing(e:MouseEvent):void { var sound:Sound = new Boing(); SoundManager.play("boing", sound); } } }
Step 10: Example Test Drive
We’re done. Press Ctrl+Enter to test the movie, and try rapidly clicking the buttons (remember to turn on your speakers). For the “Boing!” button, multiple sounds are overlapping when played. As for the “Managed Boing!” button, which makes use of the sound manager, one sound is forced to stop before the next one is played, so you won’t hear sounds mixed up together.
Step 11: Framework Integration
Commands, commands, commands. It’s always nice to integrate your work with your previous ones, right? Now we’re going to integrate the sound management framework with the command framework, along with the scene management framework. Again, if you’re not familiar with the command framework and the scene management framework, you’d better check them out in my previous tutorials (Part 1, Part 2) before going on.
Step 12: Framework PlaySound Command
The name of this command is pretty self-explanatory: it plays a sound with the sound manager.
package commands.sounds { import commands.Command; import flash.media.Sound; import flash.media.SoundTransform; import sounds.SoundManager; /** * This command plays a sound. */ public class PlaySound extends Command { public var key:String; public var sound:Sound; public var startTime:int; public var loops:int; public var transform:SoundTransform; public function PlaySound(key:String, sound:Sound, startTime:int = 0, loops:int = 0, transform:SoundTransform = null) { this.key = key; this.sound = sound; this.startTime = startTime; this.loops = loops; this.transform = transform; } override protected function execute():void { //tell the sound manager to play the sound SoundManager.play(key, sound, startTime, loops, transform); //complete the command complete(); } } }
Step 13: Framework StopSound Command
This is basically the evil cousin of the previous command. This command stops a sound track by using the sound manager.
package commands.sounds { import commands.Command; import sounds.SoundManager; /** * This command stops a sound track corresponding to a given key. */ public class StopSound extends Command { public var key:String; public function StopSound(key:String) { this.key = key; } override protected function execute():void { //tell the sound manager to stop the sound track, how evil >:] SoundManager.stop(key); //complete the command complete(); } } }
Step 14: Framework SoundLoad Command
This command loads an external MP3 file into a Sound object. Not until the loading is complete will the command’s complete() method be called. This allows us to easily chain together the command with other commands, without having to worry about handling the loading completion.
package commands.loading { import commands.Command; import flash.events.Event; import flash.media.Sound; import flash.net.URLRequest; /** * This command loads a sound. */ public class SoundLoad extends Command { public var sound:Sound; public var url:URLRequest; public function SoundLoad(sound:Sound, url:URLRequest) { this.sound = sound; this.url = url; } override protected function execute():void { //add the complete listener sound.addEventListener(Event.COMPLETE, onComplete); //begin loading sound.load(url); } private function onComplete(e:Event):void { //remove the complete listener sound.removeEventListener(Event.COMPLETE, onComplete); //complete the command complete(); } } }
Integration complete. Get prepared for our final example!
Step 15: Example Managing Sounds with Commands
In this example, we’re going to allow users to play two music on the same sound track. If a sound is to be played when the sound track is occupied, the original music is first faded out, and then the new music is played. The fading-out is handled by the TweenMaxTo command, which internally uses the special property volume provided by the TweenMax class from GreenSock Tweening Platform. The two musics are external MP3 files loaded during run-time.
Note that we’re going to use the scene management framework. If you want to refresh your memory, go check it out here.
Step 16: Example Copy Flash Document
Make a copy of the FLA file used in the previous example. Rename the buttons to “music1_btn” and “music2_btn”. You can also change the button labels to “Music 1? and “Music 2?. And add an extra button named “stop_btn”, which is for stopping the music.
Step 17: Example Copy the MP3 Files
The MP3 files can be found in the source folder. Copy them to the same folder as the FLA file.
Step 18: Example Document Class
Create a new AS file for the document class of the new FLA file. Instantiate a scene manager, and initialize it to a loading state, where the two MP3 files are loaded.
package { import flash.display.Sprite; import scenes.SceneManager; public class MusicPlayer extends Sprite { public function MusicPlayer() { //instantiate a scene manager object var sceneManager:SceneManager = new SceneManager(); //set a loading scene as the initial scene sceneManager.setScene(new LoadingScene(this)); } } }
Step 19: Example The Loading Scene
The loading scene instantiates two Sound objects for loading the two MP3 files. The buttons are set invisible at the beginning, and will be set visible again when the loading is finished. When the loading is complete, the scene immediately instructs the scene manager to transit to the main scene, as written in the overridden onSceneSet() method. Further details are described in the comments.
package { import commands.Command; import commands.data.RegisterData; import commands.loading.SoundLoad; import commands.ParallelCommand; import commands.SerialCommand; import commands.utils.SetProperties; import flash.events.Event; import flash.media.Sound; import flash.net.URLRequest; import scenes.Scene; public class LoadingScene extends Scene { //a reference to the document root container private var container:MusicPlayer; public function LoadingScene(container:MusicPlayer) { this.container = container; } override public function createIntroCommand():Command { //create two sound objects to load the two MP3 files var music1:Sound = new Sound(); var music2:Sound = new Sound(); var command:Command = new ParallelCommand(0, //hide the buttons new SetProperties(container.music1_btn, {alpha:0, visible:false}), new SetProperties(container.music2_btn, {alpha:0, visible:false}), new SetProperties(container.stop_btn, {alpha:0, visible:false}), //register the two sound objects to the data manager new RegisterData("music1", music1), new RegisterData("music2", music2), //begin the loading of the MP3 files new SoundLoad(music1, new URLRequest("Music1.mp3")), new SoundLoad(music2, new URLRequest("Music2.mp3")) ); return command; } override public function onSceneSet():void { //tell the scene manager to switch to the main scene directly after the intro command is complete sceneManager.setScene(new MainScene(container)); } } }
Step 20: Example The Main Scene
The main scene brings the hidden buttons back to visible, and registers the playMusic() method and the stopMusic() method as listeners for the click event. In the playMusic() method, a serial command is executed if the “bgm” sound track is occupied. The command first temporarily removes the click listeners, fades out the current music, stops the current music, plays the new music on the now-empty “bgm” sound track, and then finally re-adds the click listeners. The stopMusic method does basically the same thing, only that there’s no new music playback. This complex series of actions is carried out in only a few lines of clean code. Pretty neat, huh?
Note that adding and removing the listeners are common actions that are present in both the playMusic() method and the stopMusic() method. So they are factored out as two private properties, addListeners and removeListeners, initialized in the constructor.
package { import commands.Command; import commands.events.AddEventListener; import commands.events.RemoveEventListener; import commands.greensock.TweenMaxTo; import commands.ParallelCommand; import commands.SerialCommand; import commands.sounds.PlaySound; import commands.sounds.StopSound; import data.DataManager; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.media.Sound; import flash.utils.Dictionary; import scenes.Scene; import sounds.SoundManager; import sounds.SoundTrack; /** * The main scene is displayed when the loading is complete. */ public class MainScene extends Scene { //a reference to the document root container private var container:MusicPlayer; private var btn1:Sprite; private var btn2:Sprite; private var btn3:Sprite; private var dataKeys:Dictionary = new Dictionary(); private var addListeners:Command; private var removeListeners:Command; public function MainScene(container:MusicPlayer) { this.container = container; btn1 = container.music1_btn; btn2 = container.music2_btn; btn3 = container.stop_btn; //data keys used to retrieve sound objects from the data manager in the playMusic() method dataKeys[btn1] = "music1"; dataKeys[btn2] = "music2"; //this command adds all listeners addListeners = new ParallelCommand(0, new AddEventListener(btn1, MouseEvent.CLICK, playMusic), new AddEventListener(btn2, MouseEvent.CLICK, playMusic), new AddEventListener(btn3, MouseEvent.CLICK, stopMusic) ); //this command removes all listeners removeListeners = new ParallelCommand(0, new RemoveEventListener(btn1, MouseEvent.CLICK, playMusic), new RemoveEventListener(btn2, MouseEvent.CLICK, playMusic), new RemoveEventListener(btn3, MouseEvent.CLICK, stopMusic) ); } override public function createIntroCommand():Command { var command:Command = new SerialCommand(0, //fade in the buttons new ParallelCommand(0, new TweenMaxTo(btn1, 1, {autoAlpha:1}), new TweenMaxTo(btn2, 1, {autoAlpha:1}), new TweenMaxTo(btn3, 1, {autoAlpha:1}) ), //add click listeners addListeners ); return command; } /** * Plays the music. */ private function playMusic(e:Event):void { //retrieve the sound object corresponding to a data key var music:Sound = DataManager.getData(dataKeys[e.target]); //check if the BGM sound track is already playing if (SoundManager.isPlaying("bgm")) { //retrieve the playing sound track var soundTrack:SoundTrack = SoundManager.getSoundTrack("bgm"); var command:Command = new SerialCommand(0, //temporarily remove click listeners removeListeners, //fade out the current sound track new TweenMaxTo(soundTrack.channel, 1, {volume:0}), //and then stop the sound track new StopSound("bgm"), //play a new sound on the same sound track new PlaySound("bgm", music, 0, int.MAX_VALUE), //re-add click listeners addListeners ); command.start(); } else { //just play the sound if the sound track is idle SoundManager.play("bgm", music, 0, int.MAX_VALUE); } } /** * Stops the music that is currently playing. */ private function stopMusic(e:Event):void { //check if the BGM sound track is already playing if (SoundManager.isPlaying("bgm")) { //retrieve the playing sound track var soundTrack:SoundTrack = SoundManager.getSoundTrack("bgm"); var command:Command = new SerialCommand(0, //temporarily remove click listeners removeListeners, //fade out the current sound track new TweenMaxTo(soundTrack.channel, 1, {volume:0}), //and then stop the sound track new StopSound("bgm"), //re-add click listeners addListeners ); command.start(); } } } }
Step 21: Example Test the Movie
We’re ready to test the movie. Press CTRL+ENTER to test it. When you click a button, a music begins to play. After clicking another, the music fades out, and then a new one starts from the beginning.
Step 22: Extra Code Jockey Version
It’s the end of the tutorial, I know. But I just couldn’t resist from showing this to you. If you’re a code jockey, I bet you’ve already noticed that there are lots of similarities in the playMusic() method and the stopMusic() method. Why not refactor them into a single one? If you’re not interested in this code jocky version of music player, you may skip to the summary section. Otherwise, just go on reading!
First, replace all the playMusic and stopMusic in the source code with handleMusic, our new event listener. Next, delete the playMusic and the stopMusic method, and add the following handleMusic() method in the main scene class.
/** * Plays or stops the music. Code jockey version. */ private function handleMusic(e:Event):void { var music:Sound = DataManager.getData(dataKeys[e.target]); if (SoundManager.isPlaying("bgm")) { var soundTrack:SoundTrack = SoundManager.getSoundTrack("bgm"); var command:Command = new SerialCommand(0, removeListeners, new TweenMaxTo(soundTrack.channel, 1, {volume:0}), new StopSound("bgm"), //determine if we're going to play another music (music)? (new PlaySound("bgm", music, 0, int.MAX_VALUE)): (new Dummy()), addListeners ); command.start(); } else { if (music) SoundManager.play("bgm", music, 0, int.MAX_VALUE); } }
You’ll notice that the only major difference between this method and the original listeners, is the following chunk of code:
(music)? (new PlaySound("bgm", music, 0, int.MAX_VALUE)): (new Dummy()),
What the hell is this anyway? This is actually the ?: conditional operator. It’s a ternary operator, meaning that it requires three operands, A, B, and C. The statement “A?B:C” evaluates to B if A is true, or C otherwise. The music variable is supposed to hold a reference to a Sound object, so that the variable evaluates to true. However, if the event dispatcher target is the “stop_btn” button, the variable contains a null value, which evaluates to false in the ternary operator. So, if the two music buttons are clicked, the above code chunk is regarded as the single line of code below.
new PlaySound("bgm", music, 0, int.MAX_VALUE)
Otherwise, if the stop button is clicked, the code chunk is regarded as a dummy command, which simply does nothing.
new Dummy()
Just one other thing to notice. The following line of code
SoundManager.play("bgm", music, 0, int.MAX_VALUE);
is changed to
if (music) SoundManager.play("bgm", music, 0, int.MAX_VALUE);
This is for the handling the exception that the sound track is currently empty. If you can understand the code chunk above, I’m pretty sure you could figure out what this line is all about.
Test the movie by pressing Ctrl+Enter, you’ll see the exact same result as the last example. You can regard it as a fulfillment of a code jockey’s coding vanity.
Summary
In this tutorial, you have learned how to manage sounds with sound tracks. One sound track allows only one sound being played at a time, therefore ideal to represent a single character’s voice or background music. Also, you’ve seen how to integrate the sound management framework with the command framework, which gives you a huge maintainability and flexibility boost on your applications.
This is the end of the tutorial. I hope you enjoyed it. Thank you very much for reading!