AS3: SoundManager

View Documentation
Download TweenLite
Download Class

I don't normally add sounds to my projects unless the client requests it but when they do I always struggle to cleanly do it. I just had to write a utility that would allow me to do this easily and quickly as sounds are usually an afterthought. After a little bit of programming and scouring the internet for examples, the SoundManager was born.

The SoundManager is a Singleton that does exactly what it says. It has a host of methods to choose from that should make adding sounds to your projects super simple. It has a dependency to TweenLite for the sound fading (which can be taken out but I use TweenLite in a lot of projects so I just made it easy on myself). For a complete list of methods, please review the documentation.

Actionscript:
  1. package com.reintroducing.sound
  2. {
  3.     import flash.media.Sound;
  4.     import flash.media.SoundChannel;
  5.     import flash.media.SoundLoaderContext;
  6.     import flash.media.SoundTransform;
  7.     import flash.net.URLRequest;
  8.     import flash.utils.Dictionary;
  9.     import flash.utils.getQualifiedClassName;
  10.    
  11.     import gs.TweenLite;   
  12.    
  13.     /**
  14.      * The SoundManager is a singleton that allows you to have various ways to control sounds in your project.
  15.      * <p />
  16.      * The SoundManager can load external or library sounds, pause/mute/stop/control volume for one or more sounds at a time,
  17.      * fade sounds up or down, and allows additional control to sounds not readily available through the default classes.
  18.      * <p />
  19.      * This class is dependent on TweenLite (http://www.tweenlite.com) to aid in easily fading the volume of the sound.
  20.      *
  21.      * @author Matt Przybylski [http://www.reintroducing.com]
  22.      * @version 1.0
  23.      */
  24.     public class SoundManager
  25.     {
  26. //- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
  27.  
  28.         // singleton instance
  29.         private static var _instance:SoundManager;
  30.         private static var _allowInstance:Boolean;
  31.        
  32.         private var _soundsDict:Dictionary;
  33.         private var _sounds:Array;
  34.        
  35. //- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
  36.        
  37.        
  38.        
  39. //- CONSTRUCTOR -------------------------------------------------------------------------------------------
  40.    
  41.         // singleton instance of SoundManager
  42.         public static function getInstance():SoundManager
  43.         {
  44.             if (SoundManager._instance == null)
  45.             {
  46.                 SoundManager._allowInstance = true;
  47.                 SoundManager._instance = new SoundManager();
  48.                 SoundManager._allowInstance = false;
  49.             }
  50.            
  51.             return SoundManager._instance;
  52.         }
  53.        
  54.         public function SoundManager()
  55.         {
  56.             this._soundsDict = new Dictionary(true);
  57.             this._sounds = new Array();
  58.            
  59.             if (!SoundManager._allowInstance)
  60.             {
  61.                 throw new Error("Error: Use SoundManager.getInstance() instead of the new keyword.");
  62.             }
  63.         }
  64.        
  65. //- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
  66.        
  67.        
  68.        
  69. //- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
  70.    
  71.         /**
  72.          * Adds a sound from the library to the sounds dictionary for playing in the future.
  73.          *
  74.          * @param $linkageID The class name of the library symbol that was exported for AS
  75.          * @param $name The string identifier of the sound to be used when calling other methods on the sound
  76.          *
  77.          * @return Boolean A boolean value representing if the sound was added successfully
  78.          */
  79.         public function addLibrarySound($linkageID:*, $name:String):Boolean
  80.         {
  81.             for (var i:int = 0; i <this._sounds.length; i++)
  82.             {
  83.                 if (this._sounds[i].name == $name) return false;
  84.             }
  85.            
  86.             var sndObj:Object = new Object();
  87.             var snd:Sound = new $linkageID;
  88.            
  89.             sndObj.name = $name;
  90.             sndObj.sound = snd;
  91.             sndObj.channel = new SoundChannel();
  92.             sndObj.position = 0;
  93.             sndObj.paused = true;
  94.             sndObj.volume = 1;
  95.             sndObj.startTime = 0;
  96.             sndObj.loops = 0;
  97.             sndObj.pausedByAll = false;
  98.            
  99.             this._soundsDict[$name] = sndObj;
  100.             this._sounds.push(sndObj);
  101.            
  102.             return true;
  103.         }
  104.        
  105.         /**
  106.          * Adds an external sound to the sounds dictionary for playing in the future.
  107.          *
  108.          * @param $path A string representing the path where the sound is on the server
  109.          * @param $name The string identifier of the sound to be used when calling other methods on the sound
  110.          * @param $buffer The number, in milliseconds, to buffer the sound before you can play it (default: 1000)
  111.          * @param $checkPolicyFile A boolean that determines whether Flash Player should try to download a cross-domain policy file from the loaded sound's server before beginning to load the sound (default: false)
  112.          *
  113.          * @return Boolean A boolean value representing if the sound was added successfully
  114.          */
  115.         public function addExternalSound($path:String, $name:String, $buffer:Number = 1000, $checkPolicyFile:Boolean = false):Boolean
  116.         {
  117.             for (var i:int = 0; i <this._sounds.length; i++)
  118.             {
  119.                 if (this._sounds[i].name == $name) return false;
  120.             }
  121.            
  122.             var sndObj:Object = new Object();
  123.             var snd:Sound = new Sound(new URLRequest($path), new SoundLoaderContext($buffer, $checkPolicyFile));
  124.            
  125.             sndObj.name = $name;
  126.             sndObj.sound = snd;
  127.             sndObj.channel = new SoundChannel();
  128.             sndObj.position = 0;
  129.             sndObj.paused = true;
  130.             sndObj.volume = 1;
  131.             sndObj.startTime = 0;
  132.             sndObj.loops = 0;
  133.             sndObj.pausedByAll = false;
  134.            
  135.             this._soundsDict[$name] = sndObj;
  136.             this._sounds.push(sndObj);
  137.            
  138.             return true;
  139.         }
  140.        
  141.         /**
  142.          * Removes a sound from the sound dictionary.  After calling this, the sound will not be available until it is re-added.
  143.          *
  144.          * @param $name The string identifier of the sound to remove
  145.          *
  146.          * @return void
  147.          */
  148.         public function removeSound($name:String):void
  149.         {
  150.             for (var i:int = 0; i <this._sounds.length; i++)
  151.             {
  152.                 if (this._sounds[i].name == $name)
  153.                 {
  154.                     this._sounds[i] = null;
  155.                     this._sounds.splice(i, 1);
  156.                 }
  157.             }
  158.            
  159.             delete this._soundsDict[$name];
  160.         }
  161.        
  162.         /**
  163.          * Removes all sounds from the sound dictionary.
  164.          *
  165.          * @return void
  166.          */
  167.         public function removeAllSounds():void
  168.         {
  169.             for (var i:int = 0; i <this._sounds.length; i++)
  170.             {
  171.                 this._sounds[i] = null;
  172.             }
  173.            
  174.             this._sounds = new Array();
  175.             this._soundsDict = new Dictionary(true);
  176.         }
  177.  
  178.         /**
  179.          * Plays or resumes a sound from the sound dictionary with the specified name.
  180.          *
  181.          * @param $name The string identifier of the sound to play
  182.          * @param $volume A number from 0 to 1 representing the volume at which to play the sound (default: 1)
  183.          * @param $startTime A number (in milliseconds) representing the time to start playing the sound at (default: 0)
  184.          * @param $loops An integer representing the number of times to loop the sound (default: 0)
  185.          *
  186.          * @return void
  187.          */
  188.         public function playSound($name:String, $volume:Number = 1, $startTime:Number = 0, $loops:int = 0):void
  189.         {
  190.             var snd:Object = this._soundsDict[$name];
  191.             snd.volume = $volume;
  192.             snd.startTime = $startTime;
  193.             snd.loops = $loops;
  194.                
  195.             if (snd.paused)
  196.             {
  197.                 snd.channel = snd.sound.play(snd.position, snd.loops, new SoundTransform(snd.volume));
  198.             }
  199.             else
  200.             {
  201.                 snd.channel = snd.sound.play($startTime, snd.loops, new SoundTransform(snd.volume));
  202.             }
  203.            
  204.             snd.paused = false;
  205.         }
  206.        
  207.         /**
  208.          * Stops the specified sound.
  209.          *
  210.          * @param $name The string identifier of the sound
  211.          *
  212.          * @return void
  213.          */
  214.         public function stopSound($name:String):void
  215.         {
  216.             var snd:Object = this._soundsDict[$name];
  217.             snd.paused = true;
  218.             snd.channel.stop();
  219.             snd.position = snd.channel.position;
  220.         }
  221.        
  222.         /**
  223.          * Pauses the specified sound.
  224.          *
  225.          * @param $name The string identifier of the sound
  226.          *
  227.          * @return void
  228.          */
  229.         public function pauseSound($name:String):void
  230.         {
  231.             var snd:Object = this._soundsDict[$name];
  232.             snd.paused = true;
  233.             snd.position = snd.channel.position;
  234.             snd.channel.stop();
  235.         }
  236.        
  237.         /**
  238.          * Plays all the sounds that are in the sound dictionary.
  239.          *
  240.          * @param $useCurrentlyPlayingOnly A boolean that only plays the sounds which were currently playing before a pauseAllSounds() or stopAllSounds() call (default: false)
  241.          *
  242.          * @return void
  243.          */
  244.         public function playAllSounds($useCurrentlyPlayingOnly:Boolean = false):void
  245.         {
  246.             for (var i:int = 0; i <this._sounds.length; i++)
  247.             {
  248.                 var id:String = this._sounds[i].name;
  249.                
  250.                 if ($useCurrentlyPlayingOnly)
  251.                 {
  252.                     if (this._soundsDict[id].pausedByAll)
  253.                     {
  254.                         this._soundsDict[id].pausedByAll = false;
  255.                         this.playSound(id);
  256.                     }
  257.                 }
  258.                 else
  259.                 {
  260.                     this.playSound(id);
  261.                 }
  262.             }
  263.         }
  264.        
  265.         /**
  266.          * Stops all the sounds that are in the sound dictionary.
  267.          *
  268.          * @param $useCurrentlyPlayingOnly A boolean that only stops the sounds which are currently playing (default: true)
  269.          *
  270.          * @return void
  271.          */
  272.         public function stopAllSounds($useCurrentlyPlayingOnly:Boolean = true):void
  273.         {
  274.             for (var i:int = 0; i <this._sounds.length; i++)
  275.             {
  276.                 var id:String = this._sounds[i].name;
  277.                
  278.                 if ($useCurrentlyPlayingOnly)
  279.                 {
  280.                     if (!this._soundsDict[id].paused)
  281.                     {
  282.                         this._soundsDict[id].pausedByAll = true;
  283.                         this.stopSound(id);
  284.                     }
  285.                 }
  286.                 else
  287.                 {
  288.                     this.stopSound(id);
  289.                 }
  290.             }
  291.         }
  292.        
  293.         /**
  294.          * Pauses all the sounds that are in the sound dictionary.
  295.          *
  296.          * @param $useCurrentlyPlayingOnly A boolean that only pauses the sounds which are currently playing (default: true)
  297.          *
  298.          * @return void
  299.          */
  300.         public function pauseAllSounds($useCurrentlyPlayingOnly:Boolean = true):void
  301.         {
  302.             for (var i:int = 0; i <this._sounds.length; i++)
  303.             {
  304.                 var id:String = this._sounds[i].name;
  305.                
  306.                 if ($useCurrentlyPlayingOnly)
  307.                 {
  308.                     if (!this._soundsDict[id].paused)
  309.                     {
  310.                         this._soundsDict[id].pausedByAll = true;
  311.                         this.pauseSound(id);
  312.                     }
  313.                 }
  314.                 else
  315.                 {
  316.                     this.pauseSound(id);
  317.                 }
  318.             }
  319.         }
  320.        
  321.         /**
  322.          * Fades the sound to the specified volume over the specified amount of time.
  323.          *
  324.          * @param $name The string identifier of the sound
  325.          * @param $targVolume The target volume to fade to, between 0 and 1 (default: 0)
  326.          * @param $fadeLength The time to fade over, in seconds (default: 1)
  327.          *
  328.          * @return void
  329.          */
  330.         public function fadeSound($name:String, $targVolume:Number = 0, $fadeLength:Number = 1):void
  331.         {
  332.             var fadeChannel:SoundChannel = this._soundsDict[$name].channel;
  333.            
  334.             TweenLite.to(fadeChannel, $fadeLength, {volume: $targVolume});
  335.         }
  336.        
  337.         /**
  338.          * Mutes the volume for all sounds in the sound dictionary.
  339.          *
  340.          * @return void
  341.          */
  342.         public function muteAllSounds():void
  343.         {
  344.             for (var i:int = 0; i <this._sounds.length; i++)
  345.             {
  346.                 var id:String = this._sounds[i].name;
  347.                
  348.                 this.setSoundVolume(id, 0);
  349.             }
  350.         }
  351.        
  352.         /**
  353.          * Resets the volume to their original setting for all sounds in the sound dictionary.
  354.          *
  355.          * @return void
  356.          */
  357.         public function unmuteAllSounds():void
  358.         {
  359.             for (var i:int = 0; i <this._sounds.length; i++)
  360.             {
  361.                 var id:String = this._sounds[i].name;
  362.                 var snd:Object = this._soundsDict[id];
  363.                 var curTransform:SoundTransform = snd.channel.soundTransform;
  364.                 curTransform.volume = snd.volume;
  365.                 snd.channel.soundTransform = curTransform;
  366.             }
  367.         }
  368.