mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-29 19:41:25 -08:00
refactor(mediabunny): [PKG-MB-06] own audio clocks, buffers and context lifecycle
This commit is contained in:
1 parent
9d037dcbf9
commit
ccee9157a7
30 files changed
+16182
-736
No files matched your search
@@ -0,0 +1,88 @@
|
||||
import type { WrappedAudioBuffer } from 'mediabunny'
|
||||
import type { AudioClock } from './audio-clock'
|
||||
import { bufferTiming } from './audio-clock'
|
||||
|
||||
interface QueueHost extends AudioClock {
|
||||
gainNode: GainNode | null
|
||||
queuedNodes: Set<AudioBufferSourceNode>
|
||||
latestScheduledEndTime: number
|
||||
}
|
||||
|
||||
export default class NodeQueue {
|
||||
constructor(private host: QueueHost) {}
|
||||
|
||||
private release(node: AudioBufferSourceNode, stop: boolean): void {
|
||||
this.host.queuedNodes.delete(node)
|
||||
node.onended = null
|
||||
let failed = false
|
||||
let failure: unknown
|
||||
try {
|
||||
if (stop)
|
||||
node.stop()
|
||||
}
|
||||
catch (error) {
|
||||
failed = true
|
||||
failure = error
|
||||
}
|
||||
try {
|
||||
node.disconnect()
|
||||
}
|
||||
catch (error) {
|
||||
if (!failed) {
|
||||
failed = true
|
||||
failure = error
|
||||
}
|
||||
}
|
||||
if (failed)
|
||||
throw failure
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
const failures: unknown[] = []
|
||||
for (const node of [...this.host.queuedNodes]) {
|
||||
try {
|
||||
this.release(node, true)
|
||||
}
|
||||
catch (error) { failures.push(error) }
|
||||
}
|
||||
if (failures.length)
|
||||
throw failures[0]
|
||||
}
|
||||
|
||||
schedule({ buffer, timestamp }: WrappedAudioBuffer): void {
|
||||
const context = this.host.audioContext
|
||||
const gain = this.host.gainNode
|
||||
if (!context || !gain)
|
||||
return
|
||||
const timing = bufferTiming(this.host, timestamp, buffer.duration, context.currentTime)
|
||||
if (timing.offset !== null && timing.offset >= buffer.duration)
|
||||
return
|
||||
const node = context.createBufferSource()
|
||||
this.host.queuedNodes.add(node)
|
||||
try {
|
||||
node.buffer = buffer
|
||||
node.connect(gain)
|
||||
node.playbackRate.value = this.host.playbackRate
|
||||
node.onended = () => {
|
||||
if (!this.host.queuedNodes.has(node))
|
||||
return
|
||||
try {
|
||||
this.release(node, false)
|
||||
}
|
||||
catch (error) { console.warn('MediaBunny ended node cleanup:', error) }
|
||||
}
|
||||
if (timing.offset === null)
|
||||
node.start(timing.startAt)
|
||||
else
|
||||
node.start(timing.startAt, timing.offset)
|
||||
this.host.latestScheduledEndTime = Math.max(this.host.latestScheduledEndTime, timing.endMediaTime)
|
||||
}
|
||||
catch (error) {
|
||||
try {
|
||||
this.release(node, true)
|
||||
}
|
||||
catch (failure) { console.warn('MediaBunny audio node cleanup:', failure) }
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user