aalink
v0.0.2
Published
Async JavaScript interface for Ableton Link
Maintainers
Readme
aalink-js
aalink-js is a JavaScript port of aalink, an async interface for Ableton Link, built for interactive multimedia applications running in Node.js.
In aalink-js, beats arrive as awaitable promises rather than callbacks, so timing composes with ordinary control flow - loops, async functions, temporal recursion. The beat can optionally sync with other Link apps and devices on the network.
Installation
npm install aalinkaalink-js is compiled from source at install time and requires a C++ toolchain.
Usage
To connect to a Link session, create a Link object and await
link.sync() as follows:
const { Link } = require('aalink');
async function main() {
const link = new Link(120);
link.enabled = true;
for (let i = 0; i < 8; i++) {
const beat = await link.sync(1);
console.log('bang!');
}
}
main();link.sync(n) returns a Promise scheduled to resolve when Link time
reaches the next n-th beat on the timeline.
In the above example, awaiting link.sync(1) will pause and resume the
main function at beats 1, 2, 3, and so on.
Keep in mind that awaiting sync(n) does not cause a function to sleep
for the given number of beats. Regardless of the moment when the function is
suspended, it will resume when the next closest n-th beat is reached on the
shared Link timeline, e.g. awaiting for sync(2) at beat 11.5 will resume
at beat 12.
Non-integral beat syncing is supported. For example:
await link.sync(1/2); // resumes at beats 0.5, 1, 1.5...
await link.sync(3/2); // resumes at beats 1.5, 3, 4.5...Sync events can be scheduled with an offset (also expressed in beats) by
passing a second argument to sync(). Offset can be either positive
or negative. Use this to add groove to the function rhythm.
async function arpeggiate() {
for (let i = 0; i < 16; i++) {
const swing = i % 2 === 1 ? 0.25 : 0;
await link.sync(1/2, swing);
console.log('###', i);
await link.sync(1/2, 0);
console.log('@@@', i);
}
}Combine synced functions to run in series or concurrently:
const { Link } = require('aalink');
async function main() {
const link = new Link(120);
link.enabled = true;
async function sequence(name) {
for (let i = 0; i < 4; i++) {
await link.sync(1);
console.log('bang!', name);
}
}
await sequence('a');
await sequence('b');
await Promise.all([sequence('c'), sequence('d')]);
}
main();Limitations
aalink-js aims to be punctual, but it is not 100% accurate due to the processing delay in the internal scheduler and the uncertainty of event loop iterations timing.
For convenience, the numerical values of promises returned from sync()
aren't equal to the exact beat time from the moment the promises are
resolved. They correspond to the previously estimated resume times instead.
let b;
b = await link.sync(1); // b will be 1.0, returned at beat 1.00190
b = await link.sync(1); // b will be 2.0, returned at beat 2.00027
b = await link.sync(1); // b will be 3.0, returned at beat 3.00005License
Copyright (c) 2026 Artem Popov [email protected]
aalink-js is licensed under the GNU General Public License (GPL) version 3.
You can find the full text of the GPL license in the LICENSE file included
in this repository.
aalink-js includes code from node-addon-api and Ableton Link.
Copyright (c) 2017 Node.js API collaborators
Copyright 2016, Ableton AG, Berlin. All rights reserved.
