diff --git a/audio/Click.wav b/audio/Click.wav
new file mode 100644
index 0000000..b4804be
Binary files /dev/null and b/audio/Click.wav differ
diff --git a/index.html b/index.html
index c72e9c0..aac766f 100644
--- a/index.html
+++ b/index.html
@@ -48,6 +48,7 @@
+
diff --git a/script/audio.js b/script/audio.js
new file mode 100644
index 0000000..b244c7f
--- /dev/null
+++ b/script/audio.js
@@ -0,0 +1,47 @@
+/**
+ * Module that takes care of audio playback
+ */
+var AudioEngine = {
+ AUDIO_BUFFER_CACHE: {},
+ audioContext: null,
+ output: null,
+ init: function(options) {
+ // for legacy browsers
+ this.audioContext = new (window.AudioContext || window.webkitAudioContext);
+ this.output = this.audioContext.createGain();
+ this.output.connect(this.audioContext.destination);
+ },
+ options: {}, // Nothing for now
+ _playAudioBuffer: function(buffer, loop) {
+ var source = this.audioContext.createBufferSource();
+ source.buffer = buffer;
+ source.connect(this.output);
+ source.loop = loop || false;
+ source.start(0);
+ },
+ playSound: function(src, loop) {
+ var self = this;
+ this.loadAudioFile(src)
+ .then(function (buffer) {
+ self._playAudioBuffer(buffer, loop);
+ });
+ },
+ loadAudioFile(src) {
+ var self = this;
+ if (self.AUDIO_BUFFER_CACHE[src]) {
+ return new Promise(function (resolve, reject) {
+ resolve(self.AUDIO_BUFFER_CACHE[src]);
+ });
+ } else {
+ var request = new Request(src);
+ return fetch(request).then(function(response) {
+ return response.arrayBuffer();
+ }).then(function(buffer) {
+ return self.audioContext.decodeAudioData(buffer, function(decodedData) {
+ self.AUDIO_BUFFER_CACHE[src] = decodedData;
+ return self.AUDIO_BUFFER_CACHE[src];
+ });
+ });
+ }
+ }
+};
diff --git a/script/engine.js b/script/engine.js
index 4d91a3a..072007e 100644
--- a/script/engine.js
+++ b/script/engine.js
@@ -200,6 +200,7 @@
$.Dispatch('stateUpdate').subscribe(Engine.handleStateUpdates);
$SM.init();
+ AudioEngine.init();
Notifications.init();
Events.init();
Room.init();