2022-04-24 08:50:45 +00:00
|
|
|
export const audioService = {
|
2022-10-30 23:13:57 +00:00
|
|
|
unlocked: false,
|
2022-05-14 18:49:45 +00:00
|
|
|
context: null as unknown as AudioContext,
|
|
|
|
source: null as unknown as MediaElementAudioSourceNode,
|
|
|
|
element: null as unknown as HTMLMediaElement,
|
2022-04-15 14:24:30 +00:00
|
|
|
|
2022-05-14 18:49:45 +00:00
|
|
|
init (element: HTMLMediaElement) {
|
2022-04-15 14:24:30 +00:00
|
|
|
this.context = new AudioContext()
|
|
|
|
this.source = this.context.createMediaElementSource(element)
|
|
|
|
this.element = element
|
2022-10-30 23:13:57 +00:00
|
|
|
|
|
|
|
this.unlockAudioContext()
|
2022-04-15 14:24:30 +00:00
|
|
|
},
|
|
|
|
|
2022-05-14 18:49:45 +00:00
|
|
|
getContext () {
|
|
|
|
return this.context
|
2022-04-15 14:24:30 +00:00
|
|
|
},
|
|
|
|
|
2022-05-14 18:49:45 +00:00
|
|
|
getSource () {
|
|
|
|
return this.source
|
2022-04-15 14:24:30 +00:00
|
|
|
},
|
|
|
|
|
2022-05-14 18:49:45 +00:00
|
|
|
getElement () {
|
|
|
|
return this.element
|
2022-10-30 23:13:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempt to unlock the audio context on mobile devices by creating and playing a silent buffer upon the
|
|
|
|
* first user interaction.
|
|
|
|
*/
|
|
|
|
unlockAudioContext () {
|
|
|
|
['touchend', 'touchstart', 'click'].forEach(event => {
|
|
|
|
document.addEventListener(event, () => {
|
|
|
|
if (this.unlocked) return
|
|
|
|
|
|
|
|
const source = this.context.createBufferSource()
|
|
|
|
source.buffer = this.context.createBuffer(1, 1, 22050)
|
|
|
|
source.connect(this.context.destination)
|
|
|
|
source.start(0)
|
|
|
|
|
|
|
|
this.unlocked = true
|
|
|
|
}, {
|
|
|
|
once: true
|
|
|
|
})
|
|
|
|
})
|
2022-04-15 14:24:30 +00:00
|
|
|
}
|
|
|
|
}
|