External Audio Cursor API #1961
Labels
area-player
Related to the audio playback engine.
platform-all
Affects all platforms
state-accepted
This is a valid topic to work on.
Motivation
Most details have been discussed here: #1935
The plan of alphaTab is to support eventually the integration with external audio and video sources in an easy-to-use fashion (e.g. by linking to an audio or video element, or other player frameworks like youtube).
Until such a fully fledged integration exists, it is currently hard to build something outside of alphaTab due to the tight integration between the synthesizer and the cursor+highlighting logic.
With this feature it should become possible easier to integrate the cursor and highlighting with an external audio source.
Proposed Feature
alphaTab should provide an API for placing and animating the cursor via an external time provider.
The approach of Guitar Pro should act as a base for the design:
A list of sync points define how the time axis of an external audio, and the alphaTab cursor placement should align.
One possible approach to handle the alphaTab time axis, is to still generate a Midi file.
Then an external audio provides "timePositionChanged" events into alphaTab defining
isSeek
,currentTime
andendTime
in millis.alphaTab translates the time position into the respective midi tick position respecting the sync point information. A mapping logic exists in the synth already and could be refactored to something reusable: https://github.com/CoderLine/alphaTab/blob/develop/src/synth/AlphaSynth.ts#L489
https://github.com/CoderLine/alphaTab/blob/develop/src/synth/MidiFileSequencer.ts#L325
Without sync points the logic could almost be the same by just linearly mapping the time axis. With the sync points the whole time axis is extended with a relative time factor which has to be taken into account.
A non-optimized lookup is needed for
seek
scenarios where we freshly need to derive the position. This can happen like today by starting at 0 and then fast forwarding in the required steps defined by sync points and tempo changes.An optimized lookup is needed during playback. We should internally keep a state of the current place in the time axis the upcoming tempo changes and sync points. Assuming the external audio is playing normally, it is possible to "no-op" in many time update calls as nothing changes from the cursor and highlighting situation. Only when the next point-of-change occurs (change in played beats, sync point hit, tempo change..) the logic triggers.
Speed Trainer
It is quite common for media players to provide a playback speed option. The provided APIs should be able to handle this like alphaSynth today.
Metronome
Handling additional the playback of a metronome (hybrid audio) is out-of-scope for this item.
User Interactivity
Selecting playback ranges is disabled when operating in this mode. (maybe a future extension to allow looping, playback ranges etc.).
Player APIs
Most player related APIs will no-op like today (e.g. volume change or play/pause).
The following list describes whether APIs are available when the alphaTab is operating in this mode.
Methods
changeTrackMute
- not availablechangeTrackSolo
- not availablechangeTrackTranspositionPitch
- not availablechangeTrackVolume
- not availableenumerateOutputDevices
- availablegetOutputDevice
- availableloadSoundFont
- not availableloadSoundFontFromUrl
- not availablepause
- not availableplay
- not availableplayBeat
- not availableplayNote
- not availableplayPause
- not availableresetSoundFonts
- not availablescrollToCursor
- availablesetOutputDevice
- not availablestop
- not availableProperties
countInVolume
- not availableisLooping
- not availableisReadyForPlayback
- not availablemasterVolume
- not availablemetronomeVolume
- not availablemidiEventsPlayedFilter
- not availableplaybackRange
- not availableplaybackSpeed
- not availableplayer
- not availableplayerState
- not availabletickCache
- availabletickPosition
- availabletimePosition
- availableEvents
activeBeatsChanged
- availablebeatMouseDown
- availablebeatMouseMove
- availablebeatMouseUp
- availablemidiEventsPlayed
- not availableplaybackRangeChanged
- available (see note above)playedBeatChanged
- availableplayerFinished
- availableplayerPositionChanged
with mapped midi tick information. Additionally a "source" information for the event should be added to differenciate:playerReady
- not availableplayerStateChanged
- not availablesoundFontLoad
- not availablesoundFontLoaded
- not availableImplementation Details (initial thoughts)
Inside alphaTab we need an abstraction handling aspects between the different players:
IAlphaSynth
Most logic for the cursor should not change.
The new APIs should "map" the external time axis to the alphaTab time axis. And then we work like today in alphaTab in our axis (midi) to lookup and match things. We definitely need the "sync points" which additionally modify the speed (compared with the current logic only having midi tempo changes). Otherwise the cursor animations would be too fast/slow.
Sync points can likely be achieved by generating "additional" tempo changes. The BPM changes also seems to be the strategy of GuitarPro (according to the UI).
Guitar Pro handles sync points as automations on masterbar level:
While we should store them also in the data model (for file format compatiblity), we need ways of changing/adapting the sync points easy.
The text was updated successfully, but these errors were encountered: