diff --git a/README.md b/README.md
index b8a83e7..78f0bdc 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ Features
   * Random (UUID v4) channel name generation för less guessability
   * Quick-links (not recommended) using http://server/#Room:Passphrase
   * Super simple setup
+  * Notification sounds (mutable)
   * ~~Flashing title on new messages~~
 
 
@@ -50,5 +51,6 @@ Available commands:
 	/key		OurStrongPassphrase	 Sets encryption key                 
 	/leave					         Leave the room                              
 	/clear					         Clear on-screen buffer                      
+	/mute					         Toggle notification sounds                  
 	/help					         This                                        
 ```
diff --git a/public/js/cryptalk_modules/cryptalk.js b/public/js/cryptalk_modules/cryptalk.js
index 2b7fc01..a967579 100644
--- a/public/js/cryptalk_modules/cryptalk.js
+++ b/public/js/cryptalk_modules/cryptalk.js
@@ -5,13 +5,14 @@ define('cryptalk', {
 		host: ''
 	},
 	compiles: ['$'],
-	requires: ['templates']
+	requires: ['templates','sound']
 }, function ($, requires, data) {
 	var socket,
 		key,
 		room,
 		hash,
 		nick,
+		mute = false,
 
 		// Collection of DOM components
 		components = {
@@ -20,7 +21,8 @@ define('cryptalk', {
 		},
 
 		// Shortcut
-		templates = requires.templates,
+		templates = requires.templates;
+		sound = requires.sound;
 
 		// Adds a new message to the DOM
 		post = function (type, text, clearChat, clearBuffer, nick) {
@@ -93,6 +95,17 @@ define('cryptalk', {
 				post('info', $.template(templates.messages.nick_set, { nick: nick}));
 			},
 
+			mute: function () {
+				// Set nick
+				mute = !mute;
+
+				// Inform that the key has been set
+				if( mute )
+					post('info', $.template(templates.messages.muted ));
+				else
+					post('info', $.template(templates.messages.unmuted ));
+			},
+
 			join: function (payload) {
 				return (
 					room
@@ -204,8 +217,8 @@ define('cryptalk', {
 			if (!decrypted) {
 				post('error', templates.messages.unable_to_decrypt);
 			} else {
-				// Post the message, but do not clear either the chat nor the buffer.
 				post('message', sanitized, false, false, nick);
+				if( !mute ) sound.playTones(sound.messages.message);
 			}
 		})
 
@@ -219,6 +232,10 @@ define('cryptalk', {
 					} else {
 						post('server', templates.server[sanitized]);
 					}
+
+					// Play sound
+					if (sound.messages[sanitized] !== undefined && !mute ) sound.playTones(sound.messages[sanitized]);
+
 				} else {
 					post('error', templates.server.bogus);
 				}
diff --git a/public/js/cryptalk_modules/queue.js b/public/js/cryptalk_modules/queue.js
new file mode 100644
index 0000000..ce45d56
--- /dev/null
+++ b/public/js/cryptalk_modules/queue.js
@@ -0,0 +1,48 @@
+define('queue', function(){
+
+    var exports = {};
+    
+    queue = [];
+
+    exports.add_function_delayed = function(d,callback,data) { 
+        
+        queue.push(
+            {
+                func:
+                    function(){
+                        var finished = callback();
+                    },
+                pushed:Date.now(),
+                delay:d,
+                data:data
+            }
+        );
+
+    }
+
+    exports.get = function() {
+        return queue;
+    }
+
+    exports.run = function(){
+
+        for(var i=0;i<queue.length;i++){
+            var current = queue[i];
+            if (Date.now() - current.pushed > current.delay) {
+                current.func();
+                queue.splice(i,1);
+            }
+        }
+        if(!queue.length) return;
+
+        // Waste a ms to prevent callstack overflow
+        lrt_inner = Date.now();
+        while (Date.now() - lrt_inner < 1) { var a=1+1; };
+
+        exports.run();
+        
+    }
+
+    return exports;
+
+});
\ No newline at end of file
diff --git a/public/js/cryptalk_modules/sound.js b/public/js/cryptalk_modules/sound.js
new file mode 100644
index 0000000..8d11570
--- /dev/null
+++ b/public/js/cryptalk_modules/sound.js
@@ -0,0 +1,68 @@
+// Sounds module, used for emitting those annoying bl-up sounds when receiving a message
+define('sound',{requires: ['queue']}, function (requires) {
+
+	var exports = { messages: {} },
+		queue = requires.queue,
+
+		ac = new (window.AudioContext || window.webkitAudioContext || false);
+
+	// Recursive function for playing tones, takes an array of [tone,start_ms,duration_ms] - entries
+	// i is only used for recursion
+	exports.playTones = function (tones, i) {
+
+		// Parameter defaults
+		i = (i === undefined) ? 0 : i;
+
+		// Stop if we've reached the end of iteration, and require ac
+		if( !(i < Object.keys(tones).length) || !ac ) return;
+
+		// Add tones to execution queue
+		var 	current_tones = tones[i],
+				freqs = current_tones[0],
+				start = current_tones[1],
+				duration = current_tones[2];
+
+		var o = ac.createOscillator();
+		var g = ac.createGain();
+		o.frequency.value = freqs;
+		o.connect(g);
+		g.gain.value = 0.25;
+		g.connect(ac.destination);
+		queue.add_function_delayed(start,function() { o.noteOn(0); });
+		queue.add_function_delayed(start+duration,function() { o.noteOff(0); });
+
+		// Iterate, or start playing
+		i++;
+		if( i < Object.keys(tones).length  ) {
+			exports.playTones(tones,i);
+		} else {
+			queue.run();
+
+		}
+
+	}; 
+
+	exports.messages = { 
+		message: [
+			[261.63*2,0,50],
+			[261.63*3,0,50],
+			[261.63*4,50,50],
+			[261.63*5,50,50]
+		],
+		person_joined: [
+			[261.63*3,0,200],
+			[261.63*1,0,200],
+			[261.63*3,200,500],
+			[261.63*2,200,500]
+		],
+		person_left: [
+			[261.63*3,0,200],
+			[261.63*2,0,200],
+			[261.63*3,200,500],
+			[261.63*1,200,500]
+		]
+	};
+
+	return exports;
+
+});
\ No newline at end of file
diff --git a/public/js/cryptalk_modules/templates.js b/public/js/cryptalk_modules/templates.js
index 4ff4d85..8535a5a 100644
--- a/public/js/cryptalk_modules/templates.js
+++ b/public/js/cryptalk_modules/templates.js
@@ -28,6 +28,7 @@ define({
 		'	/join		RoomId			Join a room	                            \n' +
 		'	/count					Count participants of room                  \n' +
 		'	/nick		NickName		Sets an optional nick                   \n' +
+		'	/mute  				Toggle notification sounds						\n' +
 		'	/key		OurStrongPassphrase	Sets encryption key                 \n' +
 		'	/leave					Leave the room                              \n' +
 		'	/clear					Clear on-screen buffer                      \n' +
@@ -61,6 +62,10 @@ define({
 		nick_set: 				'From now on, you\'re referred to as \'{nick}\'.',
 		leave_from_nowhere: 	'How are you supposed to leave, while being nowhere?',
 
+		// Sounds
+		muted: 					'Notification sounds is now muted.',
+		unmuted: 					'Notifications sounds is now on.',
+
 		// Available variables: 'commandName'
 		unrecognized_command: 	'Unrecognized command: "{commandName}"',