al

package module
v0.0.0-...-31916ab Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2024 License: GPL-3.0 Imports: 3 Imported by: 0

README

al

Go Reference

Go bindings for Ableton Link.

About

The al package provides Go bindings for the Ableton Link C++ library. Ableton Link is a technology that synchronizes musical beat, tempo, and phase across multiple applications running on one or more devices.

The C++ library is vendored in this repository to make this module go-gettable. Supported platforms are Linux, macOS and Windows.

License

Ableton Link is dual licensed under GPLv2+ and a proprietary license. The al package is licensed under GPLv3.

Documentation

Overview

Package al implements Go bindings for Ableton Link.

Each Link instance has its own session state which represents a beat timeline and a transport start/stop state. The timeline starts running from beat 0 at the initial tempo when constructed. The timeline always advances at a speed defined by its current tempo, even if transport is stopped. Synchronizing to the transport start/stop state of Link is optional for every peer. The transport start/stop state is only shared with other peers when start/stop synchronization is enabled.

An Link instance is initially disabled after construction, which means that it will not communicate on the network. Once enabled, an Link instance initiates network communication in an effort to discover other peers. When peers are discovered, they immediately become part of a shared Link session.

Each function documents its thread-safety and realtime-safety properties. When a function is marked thread-safe, it means it is safe to call from multiple threads concurrently. When a function is marked realtime-safe, it means that it does not block and is appropriate for use in the thread that performs audio IO.

One session state capture/commit function pair for use in the audio thread and one for all other application contexts is provided. In general, modifying the session state should be done in the audio thread for the most accurate timing results. The ability to modify the session state from application threads should only be used in cases where an application's audio thread is not actively running or if it doesn't generate audio at all. Modifying the Link session state from both the audio thread and an application thread concurrently is not advised and will potentially lead to unexpected behavior.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Link struct {
	// contains filtered or unexported fields
}

Link is the representation of an abl_link instance.

func NewLink(bpm float64) *Link

NewLink Construct a new abl_link instance with an initial tempo.

Thread-safe: yes Realtime-safe: no

func (*Link) CaptureAppSessionState

func (l *Link) CaptureAppSessionState(state *SessionState)

CaptureAppSessionState capturep the current Link Session State from an application thread.

Thread-safe: no Realtime-safe: yes

Provides a mechanism for capturing the Link Session State from an application thread (other than the audio thread). After capturing the SessionState contains a snapshot of the current Link state, so it should be used in a local scope.

func (*Link) CaptureAudioSessionState

func (l *Link) CaptureAudioSessionState(state *SessionState)

CaptureAudioSessionState captures the current Link Session State from the audio thread.

Thread-safe: no Realtime-safe: yes

This function should ONLY be called in the audio thread and must not be accessed from any other threads. After capturing the SessionState holds a snapshot of the current Link SessionState, so it should be used in a local scope. The SessionState should not be created on the audio thread.

func (*Link) Clock

func (l *Link) Clock() time.Duration

Clock returns the current link clock time.

Thread-safe: yes Realtime-safe: yes

func (*Link) Close

func (l *Link) Close()

Close deletes an abl_link instance.

Thread-safe: yes Realtime-safe: no

func (*Link) CommitAppSessionState

func (l *Link) CommitAppSessionState(state *SessionState)

CommitAppSessionState commits the given Session State to the Link session from an application thread.

Thread-safe: yes Realtime-safe: no

The given session_state will replace the current Link SessionState. Modifications of the SessionState will be communicated to other peers in the session.

func (*Link) CommitAudioSessionState

func (l *Link) CommitAudioSessionState(state *SessionState)

CommitAudioSessionState commits the given Session State to the Link session from the audio thread.

Thread-safe: no Realtime-safe: yes

This function should ONLY be called in the audio thread. The given SessionState will replace the current Link state. Modifications will be communicated to other peers in the session.

func (*Link) Enable

func (l *Link) Enable(enabled bool)

Enable / Disable Link.

Thread-safe: yes Realtime-safe: no

func (*Link) EnableStartStopSync

func (l *Link) EnableStartStopSync(enabled bool)

EnableStartStopSync enables/disables start/stop synchronization.

Thread-safe: yes Realtime-safe: no

func (*Link) Enabled

func (l *Link) Enabled() bool

Enabled returns if Link is currently enabled.

Thread-safe: yes Realtime-safe: yes

func (*Link) NumPeers

func (l *Link) NumPeers() uint64

NumPeers returns how many peers are currently connected in a Link session.

Thread-safe: yes Realtime-safe: yes

func (*Link) SetNumPeersCallback

func (l *Link) SetNumPeersCallback(fn NumPeersCallbackFn)

SetNumPeersCallback registers a callback to be notified when the number of peers in the Link session changes.

Thread-safe: yes Realtime-safe: no

The callback is invoked on a Link-managed thread.

func (*Link) SetStartStopCallback

func (l *Link) SetStartStopCallback(fn StartStopCallbackFn)

SetNumPeersCallback registers a callback to be notified when the state of start/stop isPlaying changes.

Thread-safe: yes Realtime-safe: no

The callback is invoked on a Link-managed thread.

func (*Link) SetTempoCallback

func (l *Link) SetTempoCallback(fn TempoCallbackFn)

SetNumPeersCallback registers a callback to be notified when the session tempo changes.

Thread-safe: yes Realtime-safe: no

The callback is invoked on a Link-managed thread.

func (*Link) StartStopSyncEnabled

func (l *Link) StartStopSyncEnabled() bool

StartStopSyncEnabled returns if start/stop synchronization is enabled.

Thread-safe: yes Realtime-safe: no

type NumPeersCallbackFn

type NumPeersCallbackFn func(numPeers uint64)

type SessionState

type SessionState struct {
	// contains filtered or unexported fields
}

SessionState is the representation of the current local state of a client in a Link Session.

A session state represents a timeline and the start/stop state. The timeline is a representation of a mapping between time and beats for varying quanta. The start/stop state represents the user intention to start or stop transport at a specific time. Start stop synchronization is an optional feature that allows to share the user request to start or stop transport between a subgroup of peers in a Link session. When observing a change of start/stop state, audio playback of a peer should be started or stopped the same way it would have happened if the user had requested that change at the according time locally. The start/stop state can only be changed by the user. This means that the current local start/stop state persists when joining or leaving a Link session. After joining a Link session start/stop change requests will be communicated to all connected peers.

func NewSessionState

func NewSessionState() *SessionState

NewSessionState creates a new session_state instance.

Thread-safe: yes Realtime-safe: no

The session_state is to be used with the link.Capture[...]SessionState and link.Commit[...]SessionState functions to capture snapshots of the current link state and pass changes to the link session.

func (*SessionState) BeatAtTime

func (s *SessionState) BeatAtTime(atTime time.Duration, quantum float64) float64

BeatAtTime gets the beat value corresponding to the given time for the given quantum.

The magnitude of the resulting beat value is unique to this Link client, but its phase with respect to the provided quantum is shared among all session peers. For non-negative beat values, the following property holds:

fmod(beatAtTime(t, q), q) == phaseAtTime(t, q)

func (*SessionState) Close

func (s *SessionState) Close()

Close deletes a SessionState instance.

Thread-safe: yes Realtime-safe: no

func (*SessionState) ForceBeatAtTime

func (s *SessionState) ForceBeatAtTime(beat float64, atTime time.Duration, quantum float64)

ForceBeatAtTime rudely re-maps the beat/time relationship for all peers in a session.

DANGER: This function should only be needed in certain special circumstances. Most applications should not use it. It is very similar to RequestBeatAtTime except that it does not fall back to the quantizing behavior when it is in a session with other peers. Calling this function will unconditionally map the given beat to the given time and broadcast the result to the session. This is very anti-social behavior and should be avoided.

One of the few legitimate uses of this function is to synchronize a Link session with an external clock source. By periodically forcing the beat/time mapping according to an external clock source, a peer can effectively bridge that clock into a Link session. Much care must be taken at the application layer when implementing such a feature so that users do not accidentally disrupt Link sessions that they may join.

func (*SessionState) IsPlaying

func (s *SessionState) IsPlaying() bool

IsPlaying returns if transport is playing.

func (*SessionState) PhaseAtTime

func (s *SessionState) PhaseAtTime(atTime time.Duration, quantum float64) float64

PhaseAtTime gets the session phase at the given time for the given quantum.

The result is in the interval [0, quantum). The result is equivalent to fmod(beatAtTime(t, q), q) for non-negative beat values. This function is convenient if the client application is only interested in the phase and not the beat magnitude. Also, unlike fmod, it handles negative beat values correctly.

func (*SessionState) RequestBeatAtStartPlayingTime

func (s *SessionState) RequestBeatAtStartPlayingTime(beat, quantum float64)

RequestBeatAtStartPlayingTime is a convenience function which attempts to map the given beat to the time when transport is starting to play in context of the given quantum. This function evaluates to a no-op if IsPlaying equals false.

func (*SessionState) RequestBeatAtTime

func (s *SessionState) RequestBeatAtTime(beat float64, atTime time.Duration, quantum float64)

RequestBeatAtTime attempts to map the given beat to the given time in the context of the given quantum.

This function behaves differently depending on the state of the session. If no other peers are connected, then this abl_link instance is in a session by itself and is free to re-map the beat/time relationship whenever it pleases. In this case, beatAtTime(time, quantum) == beat after this funtion has been called.

If there are other peers in the session, this Link instance should not abruptly re-map the beat/time relationship in the session because that would lead to beat discontinuities among the other peers. In this case, the given beat will be mapped to the next time value greater than the given time with the same phase as the given beat.

This function is specifically designed to enable the concept of "quantized launch" in client applications. If there are no other peers in the session, then an event (such as starting transport) happens immediately when it is requested. If there are other peers, however, we wait until the next time at which the session phase matches the phase of the event, thereby executing the event in-phase with the other peers in the session. The client application only needs to invoke this function to achieve this behavior and should not need to explicitly check the number of peers.

func (*SessionState) SetIsPlaying

func (s *SessionState) SetIsPlaying(isPlaying bool, atTime time.Duration)

SetIsPlaying sets if transport should be playing or stopped, taking effect at the given time.

func (*SessionState) SetIsPlayingAndRequestBeatAtTime

func (s *SessionState) SetIsPlayingAndRequestBeatAtTime(isPlaying bool, atTime time.Duration, beat, quantum float64)

SetIsPlayingAndRequestBeatAtTime is a convenience function which starts or stop transport at a given time and attempt to map the given beat to this time in context of the given quantum.

func (*SessionState) SetTempo

func (s *SessionState) SetTempo(bpm float64, atTime time.Duration)

SetTempo sets the timeline tempo to the given bpm value, taking effect at the given time.

func (*SessionState) Tempo

func (s *SessionState) Tempo() float64

Tempo returns the tempo of the timeline, in Beats Per Minute.

This is a stable value that is appropriate for display to the user. Beat time progress will not necessarily match this tempo exactly because of clock drift compensation.

func (*SessionState) TimeAtBeat

func (s *SessionState) TimeAtBeat(beat, quantum float64) float64

TimeAtBeat gets the time at which the given beat occurs for the given quantum.

@discussion: The inverse of beatAtTime, assuming a constant tempo.

beatAtTime(timeAtBeat(b, q), q) === b.

func (*SessionState) TimeForIsPlaying

func (s *SessionState) TimeForIsPlaying() time.Duration

TimeForIsPlaying gets the time at which a transport start/stop occurs.

type StartStopCallbackFn

type StartStopCallbackFn func(isPlaying bool)

type TempoCallbackFn

type TempoCallbackFn func(tempo float64)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL