-
Notifications
You must be signed in to change notification settings - Fork 236
Description
Is there an existing issue for this?
- I have searched the existing issues
Current Behavior
After seeking while paused and then pressing play, playback appears to start (playerState changes to Playing) but the tick position never advances and no audio is produced. The player becomes permanently stuck — subsequent play/pause cycles do not recover. The only way to recover is to call stop(), seek to a new position, and play() again.
The root cause is a race condition in AlphaSynthAudioWorkletOutput. When play() is called, the AudioWorkletNode is created asynchronously via Environment.createAudioWorklet().then(...). However, the worker-side AlphaSynth immediately begins generating samples after output.play() returns and sends them via addSamples(). Since _worklet is still null during the async gap, addSamples() silently drops the samples via optional chaining (this._worklet?.port.postMessage(...)). This can cause the synth to desynchronize — in particular, _onSamplesPlayed never fires with a non-zero count, so position updates with isSeek: false are never emitted after a seek.
Expected Behavior
Samples produced between play() being called and the AudioWorkletNode being created should be buffered and delivered once the worklet is ready, not silently dropped. Playback should reliably start and advance after any sequence of seek + play operations.
Steps To Reproduce
- Load a GuitarPro file with the AlphaTab API using AudioWorklet output (the default on modern browsers)
- Start playback and let it play for a few seconds
- Pause playback
- Seek to a different position (set tickPosition or timePosition)
- Press play again
- Observe that playerState is 1 (Playing) but tickPosition and timePosition are frozen
- No audio is produced; the seek cursor does not move
Link to jsFiddle, CodePen, Project
No response
Version and Environment
alphaTab 1.8.1
Electron 34
Vite bundled, AudioWorklet output
Windows 11 ProPlatform
Node.js
Anything else?
The AlphaSynthScriptProcessorOutput does not have this bug because ScriptProcessorNode creation is synchronous in its play() method — the node is fully connected before the method returns.
Suggested fix: Buffer messages in addSamples() and resetSamples() when _worklet is null, and flush them after the worklet connects in the .then() callback. Clear the buffer on pause(). This is a minimal change to AlphaSynthAudioWorkletOutput:
// In addSamples():
if (this._worklet) {
this._worklet.port.postMessage(msg);
} else {
this._pendingMessages.push(msg);
}
// In the .then() callback after worklet creation:
for (const msg of this._pendingMessages) {
this._worklet.port.postMessage(msg);
}
this._pendingMessages = [];
// In pause():
this._pendingMessages = [];Metadata
Metadata
Assignees
Labels
Type
Projects
Status