• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excaliburjs / Excalibur / 11772012724

11 Nov 2024 04:15AM UTC coverage: 90.087% (-0.04%) from 90.128%
11772012724

push

github

eonarheim
feat: Add traditional lerp functions for ease of use

5860 of 7464 branches covered (78.51%)

0 of 12 new or added lines in 1 file covered. (0.0%)

12841 of 14254 relevant lines covered (90.09%)

25220.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

17.86
/src/engine/Util/WebAudio.ts
1
import { AudioContextFactory } from '../Resources/Sound/AudioContext';
2
import { Logger } from './Log';
3

4
export interface LegacyWebAudioSource {
5
  playbackState: string;
6
  PLAYING_STATE: 'playing';
7
  FINISHED_STATE: 'finished';
8
}
9

10
/**
11
 * Patch for detecting legacy web audio in browsers
12
 * @internal
13
 * @param source
14
 */
15
function isLegacyWebAudioSource(source: any): source is LegacyWebAudioSource {
16
  return !!source.playbackState;
×
17
}
18

19
export class WebAudio {
20
  private static _UNLOCKED: boolean = false;
1✔
21

22
  /**
23
   * Play an empty sound to unlock Safari WebAudio context. Call this function
24
   * right after a user interaction event.
25
   * @source https://paulbakaus.com/tutorials/html5/web-audio-on-ios/
26
   */
27
  static unlock(): Promise<boolean> {
28
    const promise = new Promise<boolean>((resolve, reject) => {
16✔
29
      if (WebAudio._UNLOCKED || !AudioContextFactory.create()) {
16!
30
        return resolve(true);
16✔
31
      }
32
      const unlockTimeoutTimer = setTimeout(() => {
×
33
        Logger.getInstance().warn('Excalibur was unable to unlock the audio context, audio probably will not play in this browser.');
×
34
        resolve(false);
×
35
      }, 200);
36

37
      const audioContext = AudioContextFactory.create();
×
38
      audioContext.resume().then(
×
39
        () => {
40
          // create empty buffer and play it
41
          const buffer = audioContext.createBuffer(1, 1, 22050);
×
42
          const source = audioContext.createBufferSource();
×
43
          let ended = false;
×
44

45
          source.buffer = buffer;
×
46
          source.connect(audioContext.destination);
×
47
          source.onended = () => (ended = true);
×
48

49
          source.start(0);
×
50

51
          // by checking the play state after some time, we know if we're really unlocked
52
          setTimeout(() => {
×
53
            if (isLegacyWebAudioSource(source)) {
×
54
              if (source.playbackState === source.PLAYING_STATE || source.playbackState === source.FINISHED_STATE) {
×
55
                WebAudio._UNLOCKED = true;
×
56
              }
57
            } else {
58
              if (audioContext.currentTime > 0 || ended) {
×
59
                WebAudio._UNLOCKED = true;
×
60
              }
61
            }
62
          }, 0);
63

64
          clearTimeout(unlockTimeoutTimer);
×
65
          resolve(true);
×
66
        },
67
        () => {
68
          reject();
×
69
        }
70
      );
71
    });
72

73
    return promise;
16✔
74
  }
75

76
  static isUnlocked() {
77
    return this._UNLOCKED;
×
78
  }
79
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc