S7) The Shared Moment

! and <!

Simultaneity between Runtimes, Incoming Triggers, and Distributed Composition

A single point in time. Multiple simultaneous events — sound, a percussion, a light trigger. That’s !. And when you want to wait for a signal from elsewhere, that’s <!.

Note: examples between runtimes (simultaneous SC + Python) describe the target architecture. Today, simultaneity works within the browser (JS + Web Audio).

Where does this article fit in?

! is BPscript’s simultaneity operator. It is exclusively temporal: it attaches events (triggers, gates, cv) to the same instant.


! — “at this instant, also this”

! attaches one or more secondary elements to a point in time. The first element (the primary) defines the position and duration. Everything that follows ! triggers at the same instant.

 

Sa!dha                       // plays Sa (gate:sc) + triggers dha (trigger:sc)
Sa!visual_glow               // plays Sa (gate:sc) + activates visual_glow (gate:processing)
Sa!dha!spotlight             // gate + trigger + trigger, three runtimes at the same instant
-!dha                        // silence + trigger (percussion on an empty beat)

 

Rules

  • Before !: the primary — must occupy time (gate, cv, or silence -)
  • After !: the secondaries — symbols (triggers, gates, or cv) that trigger at the same instant:

– A trigger → zero duration (impulse)
– A gate → inherits the duration of the primary
– A cv → inherits the duration of the primary

! only accepts symbols after it — it’s a purely temporal operator. To change a flag at that instant, [flag=N] is placed in the RHS, at the desired position: this is a distinct mechanism, managed by the engine (see S6).


Simultaneity between Runtimes

This is where ! becomes particularly interesting. A single temporal point can trigger events in multiple runtimes — without using polymetry:

 

@actor sitar  alphabet:raga    transport:supercollider
@actor lights alphabet:lights  transport:python

// A single temporal point, two runtimes
S -> sitar.Sa!sitar.dha!lights.spotlight sitar.Re!sitar.ti sitar.Ga!sitar.dha!lights.fadeout sitar.Pa

 

At each position:

  • Sa!dha!spotlight → SuperCollider plays Sa and dha, Python triggers spotlight
  • Re!ti → SuperCollider plays Re and ti
  • Ga!dha!fadeout → SuperCollider plays Ga and dha, Python triggers fadeout

Synchronization is exact because BP3 calculates the timing — runtimes receive their instructions for the same instant, without drift (accumulated progressive offset) or differential latency.


Simultaneous Group Macros

If the same set of simultaneous events recurs frequently, a macro can factorize it:

 

// Macros — agnostic rewriting
@macro scene_a(x) = x!visual_glow!spotlight
@macro scene_b(x) = x!visual_strobe!flash

// Usage
S -> scene_a(Sa) scene_b(Re) scene_a(Ga)

// After expansion :
// Sa!visual_glow!spotlight Re!visual_strobe!flash Ga!visual_glow!spotlight

 

The macro doesn’t know that visual_glow is Processing or that spotlight is Python (S2). It copies. Typing is checked after expansion.

This is the natural mechanism for multimedia scenes: a palette of sound+light+video combinations is defined, then used in the grammar as ordinary symbols.


<! — waiting for an external signal

<! is the mirror of !: instead of sending a signal, you wait for a signal from outside. It’s a synchronization point — the derivation pauses until the signal arrives.

 

trigger sync1()                  // declared trigger

// Waits in silence, then plays
S -> -<!sync1 Sa Re Ga

// Plays Sa, waits, then continues
S -> Sa<!sync1 Re Ga

// Waits alone then starts
S -> <!sync1 Sa Re Ga

 

The syntax follows the logic of arrows: ! exits (like ->, we send), <! enters (like <-, we receive).

The signal source

The signal source (MIDI, OSC, sensor, another BPscript instance) is configured in the mapping (S9), not in the language. Mapping is expressed via the @map directive:

 

@map cc:64 -> <!sync1            // a MIDI CC triggers sync1
@map osc:/sync/downbeat -> <!sync2  // an OSC message triggers sync2

 

BPscript doesn’t know where the signal comes from — it just knows it has to wait. The source can be a MIDI keyboard, a sensor, an OSC (Open Sound Control) message, or another BPscript instance.


Distributed Composition

! and <! open the door to distributed composition: multiple BPscript instances running on different machines, synchronized by triggers.

Perspective: the distributed composition described here is an architectural vision, not yet implemented. Waiting for an external signal (<!) and synchronization between instances fall under the downstream runtime/bridge layer, to be developed.

 

// Machine A — the melody
S -> Sa Re!sync Ga Pa!sync Dha Ni

// Machine B — waits for A's syncs
S -> <!sync rythme <!sync rythme

// Machine C — the lights, triggered by A
S -> <!sync scene_a <!sync scene_b

 

Machine A sends !sync (via OSC or MIDI). Machines B and C wait for <!sync. The result: three independent grammars, synchronized by rendezvous points.

This is the same principle as MIDI clock synchronization in an analog studio — but at the level of grammatical structures, not beats.


Chaining ! and <!

Both operators can be chained:

 

S -> Sa!dha<!sync1 Re Ga
// Plays Sa + triggers dha, then waits for sync1, then continues with Re

 

The reading order is left to right: first the outgoing triggers !, then the wait <!.


Key Takeaways

  1. ! = temporal simultaneity — attaches symbols (triggers, gates, cv) to a point in time
  2. The primary (before !) defines the duration. The secondaries (after !) trigger at the same instant
  3. ! only accepts symbols — flag mutations are written [flag=N] in the RHS, not with !
  4. Between runtimes: a single ! can target multiple runtimes at the same instant (SC, Python… — target architecture; today in browser, JS / Web Audio)
  5. <! = wait — the derivation pauses until the signal is received
  6. Simultaneous group macros factorize recurring combinations (sound + light + video)
  7. Mapping (@map) defines the source of incoming signals, not the language

Glossary

  • Primary: The element before ! — must occupy time (gate, cv, or silence)
  • Secondary: The symbol after ! — triggers at the same instant as the primary
  • Outgoing Trigger (!): Signal sent to a runtime at the time of execution
  • Incoming Trigger (<!): Synchronization point — the derivation waits for an external signal
  • Distributed Composition: Architecture where multiple BPscript instances on different machines synchronize via triggers
  • Simultaneous Group: a set of events attached to the same instant, often factorized into a macro

Links in the series

  • S3 — Types — why a trigger has zero duration
  • S6 — Flag mutations [flag=N] — distinct from !
  • S9 — Mapping — how to configure the sources of <!
  • S10 — The downstream runtime — how ! events are sent to runtimes

Prerequisites: S3, S6
Reading time: 10 min
Tags: #BPscript #triggers #simultaneity #distributed-composition #multimedia


Next article: S8 (coming soon) — Patterns, captures, and templates


Back to index