Advertisement
ulfben

SoundManager

Dec 3rd, 2011
313
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * SoundManager
  3.  * Loads a tracklist and handles all SFX and music needs for our games.
  4.  *  see tracklist.xml (http://pastebin.com/1imV9pM0) for examples of all the features:
  5.  *  track stitching, looping, offsets, volume, fadein/out, audio position with owner movieclips etc.
  6.  *
  7.  * The "event" system is an idea borrowed from FMOD.
  8.  *
  9.  * Ulf Benjaminsson, 2009-06-15
  10.  * */
  11.  
  12. import com.ulfben.noname.utils.SuperSound;
  13. import com.ulfben.noname.utils.TextLoader;
  14. import com.ulfben.noname.utils.Utils;
  15.  
  16.  class com.ulfben.noname.utils.SoundManager extends com.ulfben.noname.utils.Broadcaster {
  17.     private var _tracklistURL:String = "xml/tracklist.xml";
  18.     private var _tracks:Object;
  19.     private var _basedir:String;
  20.     private var _owners:Array;
  21.     private var _playCount:Object;
  22.     public static var DEFAULT_OWNER:MovieClip;
  23.  
  24.     public function SoundManager() {
  25.         _global["SoundManager"] = this;
  26.         _root["SoundManager"] = this;
  27.         _basedir = "";
  28.         _playCount = { };
  29.         DEFAULT_OWNER = _root.createEmptyMovieClip("soundman", _root.getNextHighestDepth());
  30.         var tl:TextLoader = new TextLoader(_tracklistURL);
  31.         tl.addEventListener("onLoad", this, "onTrackListAvaliable");
  32.         tl.loadFile();
  33.     }
  34.  
  35.     public static function get():SoundManager{
  36.         if (_global["SoundManager"] == undefined) {
  37.             _global["SoundManager"] = new SoundManager();
  38.         }
  39.         return SoundManager(_global["SoundManager"]);
  40.     }
  41.  
  42.     public function playEvent(name:String, owner:MovieClip):Void {
  43.         if (!canPlayMore(name)) { return; }
  44.         if (owner == undefined) { owner = DEFAULT_OWNER; }
  45.         var event:Object = getEventForOwner(name, owner);
  46.         var s:SuperSound = event._s;
  47.         if (s == undefined) { return; }
  48.         replaces(name, owner); //stop all events this one replaces.
  49.         if (event._stream && _tracks[name][owner]._offset == 0) {
  50.             s.setLoopsForStream(event._loops);
  51.             s.loadSound(true);//stream whenever we can; offsets (somewhat...) our lack of preloading.
  52.         }else {
  53.             if (!s.isLoaded()) { //if it hasn't made it to the cache yet
  54.                 s.loadSound(false); //request it again.
  55.             }
  56.             s.setOffset(event._offset);
  57.             s.start(event._loops); //push the button and pray it is in place and will play.
  58.         }
  59.         if (event._maxcount > 0 && s.isPlaying()) {
  60.             _playCount[name] = isNaN(_playCount[name]) ? 1 : _playCount[name] += 1;
  61.         }
  62.         if(event._fadein > 0) {
  63.             fadeIn(name, owner, event._volume, event._fadein);
  64.         }else{
  65.             s.setVolume(event._volume);
  66.         }
  67.         if(event._follow) {
  68.             s.panWith(owner);
  69.         }
  70.         if(event._leadsto != "") { //stitch events together
  71.             s.addEventListener("onSoundComplete", this, "playNextInQue");
  72.         }
  73.         if(event._maxcount > 0) {
  74.             s.addEventListener("onSoundComplete", this, "decreasePlayCount");
  75.             s.addEventListener("onSoundStop", this, "decreasePlayCount");
  76.         }
  77.     }
  78.  
  79.     public function stopAll():Void {
  80.         for (var i:Number = 0; i < _tracks.length; i++) {
  81.             var event:String = _tracks[DEFAULT_OWNER]._name;
  82.             for (var j in _tracks) {
  83.                 stopEvent(event, j);
  84.             }
  85.         }
  86.         _playCount = { };
  87.     }
  88.  
  89.     public function stopEvent(name:String, owner:MovieClip):Void {
  90.         if (owner == undefined) {
  91.             for (var i:Number = _owners.length; i >= 0; i--) {
  92.                 if (_owners == undefined) { continue;}
  93.                 stopEvent(name, _owners);
  94.             }
  95.             stopEvent(name, DEFAULT_OWNER);
  96.         }
  97.         var s:SuperSound = _tracks[name][owner]._s;
  98.         s.removeEventListener("onSoundComplete", this, "playNextInQue");
  99.         s.removeEventListener("onSoundComplete", this, "decreasePlayCount");
  100.         if (_tracks[name][owner]._fadeout == 0) {
  101.             s.stop();   //calls decreasePlayCount for us
  102.         }else {
  103.             fadeOutAndStop(name, owner, _tracks[name][owner]._fadeout);
  104.         }
  105.     }  
  106.  
  107.     public function unregisterAllOwners():Void {
  108.         for (var i:Number = _owners.length; i >= 0; i--) {
  109.             unregisterMe(_owners, i);
  110.         }
  111.         _owners = [];
  112.     }
  113.  
  114.     public function unregisterMe(owner:MovieClip, pruneIndex:Number):Void {
  115.         if (owner == DEFAULT_OWNER || owner == undefined) { return; }
  116.         if(pruneIndex == undefined){
  117.             pruneIndex = Utils.Find(owner, _owners);
  118.         }
  119.         if (owner == _owners[pruneIndex]) {
  120.             _owners.splice(pruneIndex, 1);
  121.         }
  122.         for (var i:Number = 0; i < _tracks.length; i++) {
  123.             _tracks[owner] = undefined;
  124.         }
  125.     }  
  126.  
  127.     public function fadeOutAndStop(name:String, owner:MovieClip, time:Number):Void {
  128.         if (time == undefined) { time = 0.5; }
  129.         if (owner == undefined) { owner = DEFAULT_OWNER; }
  130.         _tracks[name][owner]._s.fadeTo(0, time, true);
  131.     }
  132.  
  133.     public function fadeIn(name:String, owner:MovieClip, target:Number, time:Number):Void {
  134.         if (time == undefined) { time = 0.5; }
  135.         var event:Object = _tracks[name][owner];
  136.         event._s.setVolume(0);
  137.         event._s.fadeTo(target, time, false);
  138.     }  
  139.  
  140.     public function fadeTo(name:String, owner:MovieClip, target:Number, time:Number) {
  141.         _tracks[name][owner]._s.fadeTo(target, time, false);
  142.     }  
  143.  
  144.     public function playEventDelayed(name:String, owner:MovieClip, delay:Number):Void {
  145.         _global.setTimeout(this, "playEvent", delay, name);//todo, how do we pass owner?
  146.     }
  147.  
  148.     private function getEventForOwner(name:String, owner:MovieClip):Object {
  149.         if (owner == undefined) { owner = DEFAULT_OWNER;}
  150.         var event:Object = _tracks[name][owner];
  151.         if (event != undefined) {
  152.             return event;
  153.         }
  154.         if (_tracks[name][DEFAULT_OWNER] == undefined) { return; } //don't load events we haven't defined.
  155.  
  156.         var newEvent:Object = cloneEvent(_tracks[name][DEFAULT_OWNER]);
  157.         _owners.push(owner);
  158.         newEvent._owner = owner;
  159.         newEvent._s = new SuperSound(newEvent._name, _basedir + newEvent._file, owner);
  160.         _tracks[name][owner] = newEvent;
  161.         return newEvent;
  162.     }
  163.  
  164.     private function canPlayMore(name:String):Boolean {
  165.         var max:Number = _tracks[name][DEFAULT_OWNER]._maxcount;
  166.         if (max == 0) { return true; }
  167.         if (isNaN(_playCount[name])) { _playCount[name] = 0; }
  168.         return (_playCount[name] < max);
  169.     }
  170.  
  171.     private function decreasePlayCount(s:SuperSound):Void {
  172.         s.removeEventListener("onSoundComplete", this, "decreasePlayCount");
  173.         s.removeEventListener("onSoundStop", this, "decreasePlayCount");
  174.         if(isNaN(_playCount[s.getName()])) { _playCount[s.getName()] = 0; }
  175.         if(_playCount[s.getName()] > 0){
  176.             _playCount[s.getName()]--;
  177.         }
  178.     }
  179.  
  180.     private function replaces(name:String, owner:MovieClip):Void {
  181.         var replaces:Array = _tracks[name][owner]._ends.split("|");
  182.         for (var i:Number = 0; i < replaces.length; i++) {
  183.             if (replaces == "") { continue; }
  184.             stopEvent(replaces, owner);
  185.         }
  186.     }  
  187.  
  188.     private function playNextInQue(s:SuperSound) {
  189.         s.removeEventListener("onSoundComplete", this, "playNextInQue");
  190.         var next:String = validateOrDefaultString(_tracks[s.getName()][s.getOwner()]._leadsto);
  191.         if (next == "") { return; }
  192.         playEvent(next, s.getOwner());
  193.     }      
  194.  
  195.     private function cloneEvent(o:Object):Object {
  196.         var event:Object = { };
  197.         for (var i in o) {
  198.             event = o;
  199.         }
  200.         event._s = null;
  201.         return event;
  202.     }
  203.  
  204.     private function onTrackListAvaliable(tl:TextLoader):Void {
  205.         if(!tl.isLoaded()){
  206.             trace("SoundManager: could not load tracklist.");
  207.             return;
  208.         }
  209.         _tracks = { };
  210.         _owners = [];
  211.         var tracklist:Object = tl.getDataObject().tracklist;
  212.         _basedir = Utils.isValidString(tracklist.attributes.basedir) ? tracklist.attributes.basedir : _basedir;
  213.         for (var i:Number = 0; i < tracklist.track.length; i++) {
  214.             var attr:Object = tracklist.track.attributes;
  215.             if (_tracks[attr.eventname] != undefined) {
  216.                 continue; //duplicate
  217.             }
  218.             _tracks = _tracks[attr.eventname] = {};
  219.             _tracks[DEFAULT_OWNER] = {
  220.                 _name: validateOrDefaultString(attr.eventname),
  221.                 _file: validateOrDefaultString(attr.file),
  222.                 _volume: validateOrDefaultNumber(attr.volume,100),
  223.                 _loops: validateOrDefaultNumber(attr.loops,1),
  224.                 _fadein: validateOrDefaultNumber(attr.fadein,0),
  225.                 _fadeout: validateOrDefaultNumber(attr.fadeout,0),
  226.                 _ends: validateOrDefaultString(attr.ends),
  227.                 _leadsto: validateOrDefaultString(attr.leadsto),
  228.                 _offset: validateOrDefaultNumber(attr.offset,0),
  229.                 _follow: validateOrDefaultBool(attr.followowner,false),
  230.                 _stream: validateOrDefaultBool(attr.stream,true),
  231.                 _maxcount: validateOrDefaultNumber(attr.maxcount,0),
  232.                 _owner: DEFAULT_OWNER
  233.             };
  234.             _tracks[DEFAULT_OWNER]._loops = _tracks[DEFAULT_OWNER]._loops > 0 ? _tracks[DEFAULT_OWNER]._loops : 10000; //loop indefinetly if 0 or less
  235.             _tracks[DEFAULT_OWNER]._s = new SuperSound(_tracks[DEFAULT_OWNER]._name, _basedir + _tracks[DEFAULT_OWNER]._file, _tracks[DEFAULT_OWNER]._owner);
  236.             _tracks[DEFAULT_OWNER]._s.loadSound(false); //"preload"
  237.         }
  238.         _tracks.length = tracklist.track.length;
  239.     }
  240.  
  241.     private function validateOrDefaultBool(s:String, d:Boolean):Boolean {
  242.         if (s == undefined || s.length == 0) { return d; }
  243.         s = s.toLowerCase();
  244.         return (s == "true" || s == "yes" || s =="y") ? true : false;
  245.     }
  246.  
  247.     private function validateOrDefaultNumber(s:String, d:Number):Number {
  248.         var n:Number = Number(s);
  249.         if (!isNaN(n)) {
  250.             return n;
  251.         }
  252.         if(d == undefined){
  253.             return 0;
  254.         }
  255.         return d;
  256.     }
  257.  
  258.     private function validateOrDefaultString(s:String):String {
  259.         if(s != undefined && s != "undefined" && s != null) {
  260.             return s;
  261.         }
  262.         return "";
  263.     }
  264.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement