Sync points at runtime
Aligning a backing track to a score means putting a timestamp on each barline. The Media Sync Editor is where that authoring workflow lives โ load a waveform, tap the bar positions, export the resulting list of anchor points. Once you have that list (either from the editor or from your own UI), this page shows how to push it into a live alphaTab instance so playback follows the audio.
The demo below loads Bach's Prelude in D Minor (BWV 999) against its audio recording and lets you flip between two sync-point layouts at runtime. "Linear" stretches the 4 bars evenly across the audio; "back-loaded" spends 70% of the audio on the first two bars and rushes through the last two. Press play and toggle โ the cursor re-aligns without a reload because api.updateSyncPoints() refreshes the mapping on the running instance.
linear โ flip while paused or during playback; the cursor re-aligns immediately.Building a full waveform-and-drag-handle editor from scratch rivals what the Media Sync Editor already offers. The right workflow is: author sync points in the editor (or copy the exported list into your source), then use the runtime API below to load or refresh them on the running instance.
The data shapeโ
Each sync point lives on MasterBar.syncPoints as an Automation whose type is AutomationType.SyncPoint, with the timestamp on the automation's value. For serialization and programmatic construction, use the flat form (FlatSyncPoint), which flattens that model into a plain object with four fields:
barIndexโ the index of the target masterbar inscore.masterBars.barPositionโ a0..1ratio inside the bar.0is the downbeat,0.5is the halfway point,1is the next barline.barOccurenceโ the repeat count this sync point applies to (0for the first pass,1for the second pass through the same bar after a repeat).millisecondOffsetโ the audio timestamp in milliseconds this point maps to.
The Score model has two helpers for this shape: applyFlatSyncPoints(list) replaces every sync point on every masterbar with the entries you provide, and exportFlatSyncPoints() returns the reverse.
Refreshing after editsโ
After applying the list, call api.updateSyncPoints() to regenerate the internal midi-time mapping. Without that call, alphaTab keeps using the sync points that existed at load time.
Show it in codeโ
import * as alphaTab from '@coderline/alphatab';
const container = getAlphaTabContainer();
const api = new alphaTab.AlphaTabApi(container, {
core: { file: '/scores/song.gp' },
player: {
playerMode: alphaTab.PlayerMode.EnabledBackingTrack,
soundFont: '/soundfont/sonivox.sf2',
},
});
api.scoreLoaded.on((score) => {
const points = [
{ barIndex: 0, barPosition: 0, barOccurence: 0, millisecondOffset: 0 },
{ barIndex: 0, barPosition: 0, barOccurence: 0, millisecondOffset: 1500 },
{ barIndex: 1, barPosition: 0, barOccurence: 0, millisecondOffset: 4075 },
{ barIndex: 2, barPosition: 0, barOccurence: 0, millisecondOffset: 6475 },
{ barIndex: 3, barPosition: 0, barOccurence: 0, millisecondOffset: 10223 },
];
score.applyFlatSyncPoints(points);
api.updateSyncPoints();
});
getAlphaTabContainer() is a placeholder for the platform-specific step of obtaining the render target โ a <div> on Web, an AlphaTab control on .NET, or an AlphaTabView on Android.
Where to look nextโ
- Backing-track audio โ the mode that consumes sync points.
- Video sync โ the external-media variant that also relies on sync points.
- Media Sync Editor โ the interactive editor that produces
FlatSyncPointlists against a waveform. api.updateSyncPointsโ the refresh call in the reference.FlatSyncPoint,SyncPointData, andAutomationin the model reference.