1 | "use strict";
|
2 |
|
3 | window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 | function SoundLoader() {
|
11 | |
12 |
|
13 |
|
14 |
|
15 |
|
16 | this.sounds = {};
|
17 | |
18 |
|
19 |
|
20 |
|
21 |
|
22 | this.totalSounds = 0;
|
23 | |
24 |
|
25 |
|
26 |
|
27 |
|
28 | this.loadedSounds = 0;
|
29 | |
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | this.muted = false;
|
36 | |
37 |
|
38 |
|
39 |
|
40 |
|
41 | this.looping = {};
|
42 |
|
43 | |
44 |
|
45 |
|
46 |
|
47 |
|
48 | this.context = new window.AudioContext();
|
49 | }
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 | SoundLoader.prototype.load = function(name, path) {
|
56 | var self = this;
|
57 |
|
58 | if (this.totalSounds === 0) {
|
59 |
|
60 |
|
61 | var firstTouchHandler = function() {
|
62 | window.removeEventListener("click", firstTouchHandler);
|
63 | window.removeEventListener("keydown", firstTouchHandler);
|
64 | window.removeEventListener("touchstart", firstTouchHandler);
|
65 |
|
66 | var source = self.context.createOscillator();
|
67 | source.connect(self.context.destination);
|
68 | source.start(0);
|
69 | source.stop(0);
|
70 |
|
71 | if (self.firstPlay) {
|
72 | self.play(self.firstPlay, self.firstPlayLoop);
|
73 | } else {
|
74 | self.firstPlay = "workaround";
|
75 | }
|
76 |
|
77 | };
|
78 | window.addEventListener("click", firstTouchHandler);
|
79 | window.addEventListener("keydown", firstTouchHandler);
|
80 | window.addEventListener("touchstart", firstTouchHandler);
|
81 | }
|
82 |
|
83 | this.totalSounds++;
|
84 |
|
85 | var request = new XMLHttpRequest();
|
86 | request.open("GET", path, true);
|
87 | request.responseType = "arraybuffer";
|
88 | request.addEventListener("readystatechange", function() {
|
89 | if (request.readyState !== 4) {
|
90 | return;
|
91 | }
|
92 | if (request.status !== 200 && request.status !== 0) {
|
93 | console.error("Error loading sound " + path);
|
94 | return;
|
95 | }
|
96 | self.context.decodeAudioData(request.response, function(buffer) {
|
97 | self.sounds[name] = buffer;
|
98 | self.loadedSounds++;
|
99 | }, function(err) {
|
100 | console.error("Error decoding audio data for " + path + ": " + err);
|
101 | });
|
102 | });
|
103 | request.addEventListener("error", function() {
|
104 | console.error("Error loading sound " + path);
|
105 | });
|
106 | try {
|
107 | request.send();
|
108 | } catch (e) {
|
109 | console.error("Error loading sound", path, e);
|
110 | }
|
111 | };
|
112 |
|
113 |
|
114 |
|
115 |
|
116 | SoundLoader.prototype.allLoaded = function() {
|
117 | return this.totalSounds === this.loadedSounds;
|
118 | };
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 | SoundLoader.prototype.play = function(name, loop) {
|
125 | if (loop && this.looping[name]) {
|
126 | return;
|
127 | }
|
128 | if (!this.firstPlay) {
|
129 |
|
130 | this.firstPlay = name;
|
131 | this.firstPlayLoop = loop;
|
132 | return;
|
133 | }
|
134 | if (this.muted) {
|
135 | return;
|
136 | }
|
137 | var snd = this.sounds[name];
|
138 | if (snd === undefined) {
|
139 | console.error("Unknown sound: " + name);
|
140 | }
|
141 | var source = this.context.createBufferSource();
|
142 | source.buffer = snd;
|
143 | source.connect(this.context.destination);
|
144 | if (loop) {
|
145 | source.loop = true;
|
146 | this.looping[name] = source;
|
147 | }
|
148 | source.start(0);
|
149 | };
|
150 |
|
151 |
|
152 |
|
153 |
|
154 | SoundLoader.prototype.stop = function(name) {
|
155 | if (!this.looping[name]) {
|
156 | return;
|
157 | }
|
158 | this.looping[name].stop();
|
159 | delete this.looping[name];
|
160 | };
|
161 |
|
162 | function AudioTagSoundLoader() {
|
163 | this.sounds = {};
|
164 | this.totalSounds = 0;
|
165 | this.loadedSounds = 0;
|
166 | this.muted = false;
|
167 | this.looping = {};
|
168 | }
|
169 | AudioTagSoundLoader.prototype.load = function(name, path) {
|
170 | this.totalSounds++;
|
171 |
|
172 | var audio = new Audio();
|
173 | var self = this;
|
174 | audio.addEventListener("error", function() {
|
175 | console.error("Error loading sound " + path);
|
176 | });
|
177 | audio.addEventListener("canplaythrough", function() {
|
178 | self.sounds[name] = audio;
|
179 | self.loadedSounds++;
|
180 | });
|
181 | audio.src = path;
|
182 | audio.load();
|
183 | };
|
184 | AudioTagSoundLoader.prototype.allLoaded = function() {
|
185 | return this.totalSounds === this.loadedSounds;
|
186 | };
|
187 | AudioTagSoundLoader.prototype.play = function(name, loop) {
|
188 | if (loop && this.looping[name]) {
|
189 | return;
|
190 | }
|
191 | if (this.muted) {
|
192 | return;
|
193 | }
|
194 | var snd = this.sounds[name];
|
195 | if (snd === undefined) {
|
196 | console.error("Unknown sound: " + name);
|
197 | }
|
198 | if (loop) {
|
199 | snd.loop = true;
|
200 | this.looping[name] = snd;
|
201 | }
|
202 | snd.play();
|
203 | };
|
204 | AudioTagSoundLoader.prototype.stop = function(name) {
|
205 | var snd = this.looping[name];
|
206 | if (!snd) {
|
207 | return;
|
208 | }
|
209 | snd.loop = false;
|
210 | snd.pause();
|
211 | snd.currentTime = 0;
|
212 | delete this.looping[name];
|
213 | };
|
214 |
|
215 | function FakeSoundLoader() {}
|
216 | FakeSoundLoader.prototype.load = function() {};
|
217 | FakeSoundLoader.prototype.allLoaded = function() { return true; };
|
218 | FakeSoundLoader.prototype.play = function() {};
|
219 |
|
220 | if (window.AudioContext) {
|
221 | module.exports = SoundLoader;
|
222 | } else if (window.Audio) {
|
223 | module.exports = AudioTagSoundLoader;
|
224 | } else {
|
225 | console.log("This browser doesn't support the Web Audio API or the HTML5 audio tag.");
|
226 | module.exports = FakeSoundLoader;
|
227 | }
|