cacophony 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,26 +1,26 @@
1
- {
2
- "name": "cacophony",
3
- "version": "0.1.2",
4
- "description": "Typescript audio library with caching",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "scripts": {
8
- "build": "npm run clean && tsc --build",
9
- "clean": "tsc --build --clean",
10
- "prepublishOnly": "npm run build",
11
- "test": "echo \"Error: no test specified\" && exit 1"
12
- },
13
- "keywords": [
14
- "audio",
15
- "webaudio"
16
- ],
17
- "author": "Christopher Toth",
18
- "license": "ISC",
19
- "devDependencies": {
20
- "standardized-audio-context-mock": "^9.6.29",
21
- "typescript": "^5.1.6"
22
- },
23
- "dependencies": {
24
- "standardized-audio-context": "^25.3.55"
25
- }
26
- }
1
+ {
2
+ "name": "cacophony",
3
+ "version": "0.1.4",
4
+ "description": "Typescript audio library with caching",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "npm run clean && tsc --build",
9
+ "clean": "tsc --build --clean",
10
+ "prepublishOnly": "npm run build",
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "audio",
15
+ "webaudio"
16
+ ],
17
+ "author": "Christopher Toth",
18
+ "license": "ISC",
19
+ "devDependencies": {
20
+ "standardized-audio-context-mock": "^9.6.29",
21
+ "typescript": "^5.1.6"
22
+ },
23
+ "dependencies": {
24
+ "standardized-audio-context": "^25.3.55"
25
+ }
26
+ }
package/src/cacophony.ts CHANGED
@@ -21,6 +21,8 @@ export interface BaseSound {
21
21
  addFilter(filter: BiquadFilterNode): void;
22
22
  removeFilter(filter: BiquadFilterNode): void;
23
23
  moveTo(x: number, y: number, z: number): void;
24
+ volume: number;
25
+
24
26
  loop(loopCount?: LoopCount): LoopCount;
25
27
  }
26
28
 
@@ -68,7 +70,6 @@ export class Cacophony {
68
70
  return filter;
69
71
  }
70
72
 
71
-
72
73
  pause() {
73
74
  if ('suspend' in this.context) {
74
75
  this.context.suspend();
@@ -91,6 +92,14 @@ export class Cacophony {
91
92
  this.globalGainNode.gain.value = volume;
92
93
  }
93
94
 
95
+ get volume(): number {
96
+ return this.globalGainNode.gain.value;
97
+ }
98
+
99
+ set volume(volume: number) {
100
+ this.setGlobalVolume(volume);
101
+ }
102
+
94
103
  mute() {
95
104
  this.prevVolume = this.globalGainNode.gain.value;
96
105
  this.setGlobalVolume(0);
@@ -154,7 +163,7 @@ export class Sound extends FilterManager implements BaseSound {
154
163
 
155
164
  play(): Playback[] {
156
165
  const playback = this.preplay();
157
- playback.forEach(p => p.source.start());
166
+ playback.forEach(p => p.source!.start());
158
167
  return playback;
159
168
  }
160
169
 
@@ -184,7 +193,7 @@ export class Sound extends FilterManager implements BaseSound {
184
193
  return this.loopCount;
185
194
  }
186
195
  this.loopCount = loopCount;
187
- this.playbacks.forEach(p => p.source.loop = true);
196
+ this.playbacks.forEach(p => p.source!.loop = true);
188
197
  return this.loopCount;
189
198
  }
190
199
 
@@ -197,14 +206,22 @@ export class Sound extends FilterManager implements BaseSound {
197
206
  super.removeFilter(filter);
198
207
  this.playbacks.forEach(p => p.removeFilter(filter));
199
208
  }
200
- }
201
209
 
210
+ get volume(): number {
211
+ return this.globalGainNode.gain.value;
212
+ }
213
+
214
+ set volume(volume: number) {
215
+ this.globalGainNode.gain.value = volume;
216
+ this.playbacks.forEach(p => p.volume = volume);
217
+ }
218
+ }
202
219
 
203
220
  class Playback extends FilterManager implements BaseSound {
204
221
  context: AudioContext;
205
- source: AudioBufferSourceNode;
206
- gainNode: GainNode;
207
- panner: PannerNode;
222
+ source?: AudioBufferSourceNode;
223
+ gainNode?: GainNode;
224
+ panner?: PannerNode;
208
225
  loopCount: LoopCount = 0;
209
226
  currentLoop: number = 0;
210
227
  buffer: IAudioBuffer | null = null;
@@ -223,7 +240,6 @@ class Playback extends FilterManager implements BaseSound {
223
240
  source.start();
224
241
  }
225
242
 
226
-
227
243
  handleLoop(): void {
228
244
  if (this.loopCount === 'infinite' || this.currentLoop < this.loopCount) {
229
245
  this.currentLoop++;
@@ -234,35 +250,68 @@ class Playback extends FilterManager implements BaseSound {
234
250
  }
235
251
 
236
252
  play() {
253
+ if (!this.source) {
254
+ throw new Error('Cannot play a sound that has been cleaned up');
255
+ }
237
256
  this.source.start();
238
257
  return [this];
239
258
  }
240
259
 
260
+ get volume(): number {
261
+ if (!this.gainNode) {
262
+ throw new Error('Cannot get volume of a sound that has been cleaned up');
263
+ }
264
+ return this.gainNode.gain.value;
265
+ }
266
+
241
267
  set volume(v: number) {
268
+ if (!this.gainNode) {
269
+ throw new Error('Cannot set volume of a sound that has been cleaned up');
270
+ }
242
271
  this.gainNode.gain.value = v;
243
272
  }
244
273
 
245
- fadeIn(time: number, FfadeType: FadeType = 'linear'): Promise<void> {
274
+ fadeIn(time: number, fadeType: FadeType = 'linear'): Promise<void> {
246
275
  return new Promise(resolve => {
247
- // Setting the initial gain value to 0
248
- this.gainNode.gain.setValueAtTime(0, this.context.currentTime);
249
- switch (FfadeType) {
276
+ if (!this.gainNode) {
277
+ throw new Error('Cannot fade in a sound that has been cleaned up');
278
+ }
279
+
280
+ const initialVolume = this.gainNode.gain.value;
281
+ const targetVolume = 1; // Assuming the target volume after fade-in is 1 (full volume)
282
+
283
+ // Reset volume to 0 to start the fade-in process
284
+ this.gainNode.gain.value = 0;
285
+
286
+ switch (fadeType) {
250
287
  case 'exponential':
251
- // Scheduling an exponential fade up
252
- this.gainNode.gain.exponentialRampToValueAtTime(1, this.context.currentTime + time);
288
+ // Start at a low value (0.01) because exponentialRampToValueAtTime cannot ramp from 0
289
+ this.gainNode.gain.setValueAtTime(0.01, this.context.currentTime);
290
+ this.gainNode.gain.exponentialRampToValueAtTime(targetVolume, this.context.currentTime + time);
253
291
  break;
254
292
  case 'linear':
255
- // Scheduling a linear ramp to the target gain value over the given duration
256
- this.gainNode.gain.linearRampToValueAtTime(1, this.context.currentTime + time);
293
+ this.gainNode.gain.linearRampToValueAtTime(targetVolume, this.context.currentTime + time);
294
+ break;
257
295
  }
258
- // Resolving the Promise after the fade-in time
259
- setTimeout(() => resolve(), time * 1000);
296
+
297
+ // Resolve the Promise after the fade-in time
298
+ setTimeout(() => {
299
+ // Ensure the final volume is set to the target volume
300
+ if (!this.gainNode) {
301
+ throw new Error('Cannot fade in a sound that has been cleaned up');
302
+ }
303
+ this.gainNode.gain.value = targetVolume;
304
+ resolve();
305
+ }, time * 1000);
260
306
  });
261
307
  }
262
308
 
263
309
  fadeOut(time: number, fadeType: FadeType = 'linear'): Promise<void> {
264
310
  return new Promise(resolve => {
265
311
  // Storing the current gain value
312
+ if (!this.gainNode) {
313
+ throw new Error('Cannot fade out a sound that has been cleaned up');
314
+ }
266
315
  const initialVolume = this.gainNode.gain.value;
267
316
  switch (fadeType) {
268
317
  case 'exponential':
@@ -279,7 +328,23 @@ class Playback extends FilterManager implements BaseSound {
279
328
  });
280
329
  }
281
330
 
331
+ cleanup(): void {
332
+ if (this.source) {
333
+ this.source.disconnect();
334
+ this.source = undefined;
335
+ }
336
+ if (this.gainNode) {
337
+ this.gainNode.disconnect();
338
+ this.gainNode = undefined;
339
+ }
340
+ this.filters.forEach(filter => filter.disconnect());
341
+ this.filters = [];
342
+ }
343
+
282
344
  loop(loopCount?: LoopCount): LoopCount {
345
+ if (!this.source) {
346
+ throw new Error('Cannot loop a sound that has been cleaned up');
347
+ }
283
348
  if (loopCount === undefined) {
284
349
  return this.source.loop === true ? 'infinite' : 0;
285
350
  }
@@ -290,16 +355,25 @@ class Playback extends FilterManager implements BaseSound {
290
355
  }
291
356
 
292
357
  stop(): void {
358
+ if (!this.source) {
359
+ throw new Error('Cannot stop a sound that has been cleaned up');
360
+ }
293
361
  this.source.stop();
294
362
  }
295
363
 
296
364
  pause(): void {
365
+ if (!this.source) {
366
+ throw new Error('Cannot pause a sound that has been cleaned up');
367
+ }
297
368
  if ('suspend' in this.source.context) {
298
369
  this.source.context.suspend();
299
370
  }
300
-
301
371
  }
372
+
302
373
  resume(): void {
374
+ if (!this.source) {
375
+ throw new Error('Cannot resume a sound that has been cleaned up');
376
+ }
303
377
  if ('resume' in this.source.context) {
304
378
  this.source.context.resume();
305
379
  }
@@ -316,12 +390,18 @@ class Playback extends FilterManager implements BaseSound {
316
390
  }
317
391
 
318
392
  moveTo(x: number, y: number, z: number): void {
393
+ if (!this.panner) {
394
+ throw new Error('Cannot move a sound that has been cleaned up');
395
+ }
319
396
  this.panner.positionX.value = x;
320
397
  this.panner.positionY.value = y;
321
398
  this.panner.positionZ.value = z;
322
399
  }
323
400
 
324
401
  private refreshFilters(): void {
402
+ if (!this.source || !this.gainNode) {
403
+ throw new Error('Cannot update filters on a sound that has been cleaned up');
404
+ }
325
405
  let connection = this.source;
326
406
  this.source.disconnect();
327
407
  connection = this.applyFilters(connection);
@@ -391,5 +471,13 @@ export class Group implements BaseSound {
391
471
  this.sounds.forEach(sound => sound.moveTo(x, y, z));
392
472
  }
393
473
 
474
+ get volume(): number {
475
+ return this.sounds[0].volume;
476
+ }
477
+
478
+ set volume(volume: number) {
479
+ this.sounds.forEach(sound => sound.volume = volume);
480
+ }
481
+
394
482
  }
395
483
 
@@ -1,5 +0,0 @@
1
- import { AudioBuffer, AudioContext, registrar } from 'standardized-audio-context-mock';
2
-
3
- import { Cacophony } from './cacophony';
4
-
5
-