Beatshifting

Craig Latta has written a Caffeine app implementation of the *Beatshifting* algorithm for collaborative, synchronized, and out-of-phase musical performances. post , github

two Beatshifting timelines. png

Beatshifting uses network latency as a rhythmic element, using offsets of beats as timestamps, with a shared Metronome and score.

> I was inspired to write the Beatshifting app by NINJAM page , a similar system that has hosted many hours of joyous sessions. archive There are a few interesting twists I think I can bring to the technology, through late-binding of audio rendering.

NINJAM also synchronizes distributed streams of rhythmic music. It works by using a server to collect an entire measure of audio from the performers’ timestamped streams, stamps them all with an upcoming measure number, and sends them back to each performer. Each performer’s system plays the collected measures with the start times aligned. In effect, each performer plays along with what everyone else did a measure ago. Each performer must receive audio only by the start of the upcoming measure, rather than fast enough to create the illusion of simultaneity. Beatshifting gives more control over the session to each performer, and to an audience as well. Each performer can modify not only the local volume levels of the other performers, but also their delays and instruments. Each performer can also change the tempo and time signature of the session. A session can have an audience as well, and each audience member is really a performer who hasn’t played anything yet. It’s straightforward to have an arbitrary number of participants in a session because Beatshifting takes the form of a web app. Each participant only needs to visit a session link in a web browser, rather than use a special digital audio workstation (DAW) app. By default, Beatshifting uses MIDI event messages instead of audio, using much less bandwidth even with a large group.

To Deliver Events to each participant’s web browser, Beatshifting uses the Croquet replication service. Croquet is able to replicate and synchronize any JavaScript object in every participant’s web browser, up to 60 times per second. Beatshifting uses this to provide a shared score. Music events like notes and fader movements can be scheduled into the score by any participant, and from code run by the score itself.

One piece of code the score runs broadcasts events indicating that measures have elapsed, so that the web browsers can render metronome clicks. There are three kinds of metronome clicks, for ticks, beats, and measures. For example, with a time signature of 6/8, there are two beats per measure, and three ticks per beat. Each tick is an eighth-note, so each beat is a dotted-quarter note. The sequence of clicks one hears is:

* measure * tick * tick * beat * tick * tick At a tempo of 120 beats per minute, or 240 clicks per 60,000 milliseconds, there are 250 milliseconds between clicks. Each time a web browser receives a measure-elapsed event, it schedules MIDI events for the next measure’s clicks with the local MIDI output interface. Since each web browser knows the starting time of the session in its output MIDI interface’s timescale, it can calculate the timestamps of all ensuing clicks. When a performer plays a note, their web browser notes the offset in milliseconds between when the note was played and the time of the most recent click. The web browser then publishes an event-scheduling message, to which the score is subscribed. The score then broadcasts a note-played event to all the web browsers. Again, it’s up to each web browser to schedule a corresponding MIDI note with its local MIDI output interface. The local timestamp of that note is chosen to be the same millisecond offset from some future click point. How far in the future that click is can be chosen based on who played the note, or any other element of the event’s data. Each web browser can also choose other parameters for each event, like instrument, volume level, and panning position. Quantities like tempo are part of the score’s state, and can be changed by any performer or audience member. Croquet ensures that the changed JavaScript variables are synchronized in all the participants’ web browsers. With so many decisions about how music events are rendered left to each web browser, the mix that each participant hears can be wildly different. The only constants are the millisecond beat offsets of each performer’s notes. I think it’ll be fun to compare recordings of these mixes after the fact, and to make new ones from individual recorded tracks. There’s no server that any participant needs to set up, and the Croquet service knows nothing of the Beatshifting protocol. This makes it very easy to start and join new sessions.

the current Beatshifting UI. png

# next steps

The current Beatshifting UI has controls for joining a session, enabling the local scheduling of metronome clicks, and changing the tempo and time signature of a session.

If one is using a MIDI output interface connected to a DAW, then one may use the DAW to control instruments, volume, panning, and so on.

> I’d also like to provide the option of all MIDI event rendering performed by the web browser, and a UI for controlling and recording that. I’ve established the use of the ToneJS audio framework for rendering events, and am now developing the UI.

On April 23, 2021, Craig conducted a world premiere of Beatshifting as part of the Netherlands' Coding Live concert series.

He has written an animated 3D visualization of the Beatshifting algorithm, which can be driven from live session data. This movie is an annotated slow-motion version:

VIMEO 541502389 visualizing the Beatshifting algorithm

> I’m excited about the creative potential of Beatshifting sessions. Please contact me if you’re interested in playing or coding for this medium! post

~

beatshifting enlarge

https://wiki.ralfbarkow.ch/assets/caffeine/beatshifting/index.html

caffeine/beatshifting

FIXME

vue-scrolly npm and

BitBltPlugin

(anonymous) @ https://wiki.ralfbarkow.ch/assets/caffeine/js/squeakjs/plugins/BitBltPlugin.js:1895 load @ https://wiki.ralfbarkow.ch/assets/caffeine/js/squeakjs/squeak.js:86 toRun @ https://wiki.ralfbarkow.ch/assets/caffeine/js/squeakjs/squeak.js:93 (anonymous) @ https://wiki.ralfbarkow.ch/assets/caffeine/js/squeakjs/plugins/BitBltPlugin.js:8