# Improved Sound Control System

After a bit of work, I've changed my code a lot from the previous question:

I was recommended by George Mauer and schism to make a better structural design, so hopefully this new build is a bit sleeker in design. I will note that my main target is optimal performance. But like Mr. Mauer said, it is most likely negligible in this particular case.

What I've attempted since is removing duplicate code at the same time optimizing performance and fixing design. Here is what I came up with:

var MediaMaster = new (function(){
var sounds = {};// a container of Audio instances and names(keys) as a reference to their respective values.

// Master Controll of sounds
var liveSounds = [],
instanceVolume = {},
globalVolume = 1;

var SB = {muted: false, previousVolume:1};
this.soundBatch = this.sBatch = SB;
SB.toggleMute = function(){
if( SB.muted === false ){
// mute everything
liveSounds.forEach(function(snd){
snd.previousVolume = snd.volume;
snd.volume = 0;
});
SB.previousVolume = globalVolume;
globalVolume = 0;
return (SB.muted = true);
}
//unmute everything
liveSounds.forEach(function(snd){
snd.volume = snd.previousVolume;
delete snd.previousVolume;
});
globalVolume = SB.previousVolume;
return (SB.muted = false);
};

// Hide specific soundBatch functionality
(function(SB){
function killSound(snd){
snd.pause();
snd.onended();
snd.currentTime = 0;
}
function globalVolumeChange(v){ globalVolume = Math.pow(v,2);}
function globalStop(){liveSounds.forEach(function(snd){killSound(snd)});}
function globalPause(){ liveSounds.forEach(function(snd){snd.pause();}); }
function globalGetLive(){return liveSounds.slice();}
//Applies a callback to anything that passes the filter
function instanceApply(name, callback){
var match = sounds[name].src;
liveSounds.forEach(function(snd){
if( snd.src !== match ) return;
callback(snd);
});
}

SB.volume = function(name, v){
if(!name)return globalVolumeChange(v);
instanceVolume[name] = Math.pow(v,2);
};
SB.stop = SB.kill = function( name ){
if(!name)return globalStop();
instanceApply(name, killSound);
};
SB.pause = function( name ){
if(!name)return globalPause();
instanceApply(name, function(snd){ snd.pause(); });
}
SB.getLive = function( name ){
if(!name)return globalGetLive();
return liveSounds.filter(function(snd){ return( snd.src === match );});
}
})(this.soundBatch);

var prototypePlay = Audio.prototype.play;//keep a reference

// Getting  sounds
this.sound = function(name){
var snd = new Audio( sounds[name].src );

snd.volume = instanceVolume[name];
snd.play = function(){
var that = this;// used for removing "liveSounds" this conflict.
that.volume *= globalVolume;
prototypePlay.apply(that);
liveSounds.push(that);
this.onended = function(){ liveSounds.splice( liveSounds.indexOf(that), 1 );};
};
return snd;
};
})();


If you're looking for an ever bigger picture of what this belongs too, it is a part of my Game Framework I started July 4th. Look for "mediaManager.js"

• var SB = {muted: false, previousVolume:1}: you should have whitespace after your last colon.

• Math.pow(v,2): you should have a space after the comma.

• In the following four lines, you should have extra whitespace in between your brackets:
function globalVolumeChange(v){ globalVolume = Math.pow(v,2);}
function globalStop(){liveSounds.forEach(function(snd){killSound(snd)});}
function globalPause(){ liveSounds.forEach(function(snd){snd.pause();}); }
function globalGetLive(){return liveSounds.slice();}

• if( snd.src !== match ) return;: you should wrap this in curly brackets, as it can have undesired effects
• You should avoid having extra space in your if-else statement brackets like in the point above, and in a few different places.
• I appreciate the attention to detail you got there, and I was well unaware of any oddities with returning after a conditional. I've seen it used so many times I just stopped wrapping it myself! Also, the line return(SB.muted = true); was necessary as I was returning the value at the same time changing it. Prefixing it would only effect the return value and not the mute variable itself. Also, I apparently didn't change my globalVolumeChange function to what it is now.. That's where SB.muted really does work. Jul 7, 2015 at 23:01