|
| 1 | +let audioContext: AudioContext | null = null; |
| 2 | + |
1 | 3 | /** |
2 | 4 | * Plays a sound using the Web Audio API. |
3 | 5 | * |
4 | 6 | * @param context - The audio context to use for generating the sound. |
5 | 7 | * @param frequency - The frequency of the sound in Hertz |
6 | | - * @param duration - The duration of the sound in milliseconds. |
| 8 | + * @param durationMs - The duration of the sound in milliseconds. |
7 | 9 | * @param volume - The volume of the sound, typically between 0 and 1. |
8 | 10 | */ |
9 | 11 | export const playSound = ( |
10 | | - context: AudioContext, |
11 | 12 | frequency: number, |
12 | | - duration: number, |
13 | | - volume: number, |
| 13 | + durationMs: number, |
| 14 | + volumePct: number, |
14 | 15 | ) => { |
15 | 16 | if (frequency <= 0) { |
16 | 17 | throw new Error("Frequency must be a positive number."); |
17 | 18 | } |
18 | 19 |
|
19 | | - if (duration <= 0) { |
| 20 | + if (durationMs <= 0) { |
20 | 21 | throw new Error("Duration must be a positive number."); |
21 | 22 | } |
22 | 23 |
|
23 | | - if (volume < 0 || volume > 1) { |
| 24 | + if (volumePct < 0 || volumePct > 1) { |
24 | 25 | throw new Error("Volume must be between 0 and 1."); |
25 | 26 | } |
26 | 27 |
|
27 | | - const oscillatorNode = context.createOscillator(); |
28 | | - oscillatorNode.frequency.setValueAtTime(frequency, context.currentTime); |
| 28 | + audioContext ??= new AudioContext(); |
| 29 | + |
| 30 | + const oscillatorNode = audioContext.createOscillator(); |
| 31 | + oscillatorNode.frequency.setValueAtTime(frequency, audioContext.currentTime); |
29 | 32 |
|
30 | | - const gainNode = context.createGain(); |
31 | | - gainNode.gain.setValueAtTime(volume, context.currentTime); |
| 33 | + const gainNode = audioContext.createGain(); |
| 34 | + gainNode.gain.setValueAtTime(volumePct, audioContext.currentTime); |
32 | 35 |
|
33 | 36 | // Creates the smooth fades-in / fade-out sound effect (Avoids the popping sounds) |
34 | | - gainNode.gain.linearRampToValueAtTime(volume, context.currentTime + 0.01); |
| 37 | + gainNode.gain.linearRampToValueAtTime( |
| 38 | + volumePct, |
| 39 | + audioContext.currentTime + 0.01, |
| 40 | + ); |
35 | 41 | gainNode.gain.linearRampToValueAtTime( |
36 | 42 | 0, |
37 | | - context.currentTime + duration / 1000 - 0.01, |
| 43 | + audioContext.currentTime + durationMs / 1000 - 0.01, |
38 | 44 | ); |
39 | 45 |
|
40 | 46 | oscillatorNode.connect(gainNode); |
41 | | - gainNode.connect(context.destination); |
| 47 | + gainNode.connect(audioContext.destination); |
42 | 48 |
|
43 | 49 | oscillatorNode.start(); |
44 | | - oscillatorNode.stop(context.currentTime + duration / 1000); |
| 50 | + oscillatorNode.stop(audioContext.currentTime + durationMs / 1000); |
45 | 51 | }; |
0 commit comments