Beat Analyzer

At a glance

The beat-analyzer is the system’s beat clock and its level meters. It has no box and no screen of its own: it is a program on the A³ Core machine, sitting on the same JACK audio graph as REAPER.

It does two jobs:

  • The beat. It sends /beat — the beat in the bar, the bar and the tempo — to the devices. A³ Motion follows it in EXT and PIO, the A³ Mixer’s tap keys blink with it.

  • The meters. Twelve peak/RMS meters, 25 times a second. The coronas around A³ Motion’s channel blobs, the glow of its sphere, the lightning of its speakers and the A³ Mixer’s VU meters all come from here.

Where the beat comes from is your choice, and you make it on A³ Motion’s clock key.

  • beat-analyzer repository — not under the a3-audio organisation, but part of the same system and versioned along with it

  • Built on BTrack for the tempo detection

Clock modes

The beat-analyzer has three clock modes. A³ Motion’s clock key picks one: each tap on the key steps INT → EXT → PIO and tells the beat-analyzer the new mode with /clockmode.

A³ Motion reads

/clockmode

Mode

Where the beat comes from

INT

0

a3motion

A³ Motion. You tap the tempo on Motion, Motion sends /beat, and the beat-analyzer passes it on to everyone else

EXT

1

intern

The music. The beat-analyzer listens to the audio and finds the beat itself

PIO

2

pioneer

The Pro DJ Link tempo master — a CDJ, or StemDeck as master

What each mode needs

INT — a3motion. Nothing but A³ Motion. Motion sends its own /beat to port 7775; the beat-analyzer relays each one to every target in its configuration except the one named motion, so Motion never hears its own beat come back. In this mode the beat-analyzer’s own clock is paused, and a /tap it receives does nothing here.

EXT — intern. Music on the beat-analyzer’s input. Its JACK input bpm_1 is patched from REAPER by Core’s patchbay, so whatever REAPER hands it is what it listens to. From that it finds onsets and a tempo, and a clock of its own counts the beats — it keeps counting between detected beats, and at the last tempo if the music stops. Tapping works here:

  • The first tap after a pause of more than two seconds sets the one: the beat restarts at 1, at the tempo it had.

  • From the second tap on, the tempo is taken from your taps (the middle of the last eight intervals); from the third on, every tap also puts the beat back on 1.

  • A tapped tempo outside BPM_MIN–BPM_MAX is ignored.

Warning

A tapped tempo stays. Once you have tapped a tempo in EXT, the beat-analyzer keeps it: it still follows the music’s beats for the phase, but no longer changes its tempo by itself. A new tempo takes new taps; the analysis only goes back to finding the tempo on its own after the beat-analyzer is restarted.

PIO — pioneer. A Pro DJ Link network the Core machine is on. The beat-analyzer joins it as a virtual CDJ, number 7, and listens on UDP ports 50000–50002. It follows the tempo master: the player whose status says master while it plays. Until it has heard who the master is, it takes the beats of any player. The tempo it sends is the master’s track tempo with its pitch applied — what the master’s display shows.

The Pro DJ Link beat says where the beat is in the bar, not which bar it is, so in PIO the bar number in /beat is always 0.

Note

No CDJs? Use StemDeck as the master. StemDeck can be the tempo master on the link by itself, and PIO then follows StemDeck exactly as it would follow a CDJ. See Playing without CDJs.

Switching modes by hand

A³ Motion’s clock key is the normal way. Anything that can send OSC can do the same — /clockmode with an integer to port 7775 on the Core machine. With oscsend from liblo-tools, on the Core machine itself:

oscsend localhost 7775 /clockmode i 2     # 0 a3motion, 1 intern, 2 pioneer

A value outside 0–2 is clamped to the nearest mode. A³ Motion does not hear about a change made this way: its clock key keeps showing what it showed.

Playing without CDJs: StemDeck as the tempo master

With no CDJs in the booth, StemDeck can drive the whole clock. The chain, as the code runs it:

StemDeck, deck with MASTER on
   │  Pro DJ Link: a beat packet on every beat, a status packet every 200 ms,
   │  as virtual CDJ 6, sent as broadcast on UDP 50001 / 50002
   ▼
beat-analyzer, clock mode 2 (pioneer), virtual CDJ 7
   │  takes StemDeck as the tempo master: it says master, and it plays
   │  /beat  beat-in-bar, 0, bpm
   ▼
A³ Motion on PIO, A³ Mixer's tap keys, every other /beat target
  1. Start StemDeck and load a set on a deck. Wait for the BPM readout: a deck sends nothing until its tempo analysis is done.

  2. Press MASTER on that deck — or just press PLAY on it: with no master chosen, the only playing deck becomes master by itself (not under SYNC: PIO, and not once you have turned MASTER off by hand). The top bar reads PIO master: A (or B).

  3. On A³ Motion, tap the clock key until it reads PIO.

  4. The BPM on A³ Motion now follows the master deck, tempo fader included.

Where the one is. StemDeck counts the bar from the first beat of the track’s beat grid, not from anything it knows about the music. If A³ Motion’s downbeat falls on the wrong beat, that is where to look.

A stopped master stays master and sends no beats. A³ Motion then carries on at the last tempo it had, as it does whenever the beats stop.

The same works on one machine: StemDeck and the beat-analyzer both listen on ports 50000–50002, and because StemDeck sends as broadcast, both of them get every packet regardless of which started first.

The meters

The beat-analyzer measures twelve JACK inputs, vu_1 … vu_12, and sends each as a peak and an RMS value between 0 and 1, all twelve in one packet. It gives a channel no meaning of its own: which signal is on which meter is decided by the JACK patching alone. In the A³ setup:

JACK input

OSC address

Signal

A³ Motion shows it as

vu_1 … vu_4

/vu/0 … /vu/3

mixer channels 1–4

the corona around each channel blob

vu_5

/vu/4

subwoofer

the glow of the sphere

vu_6 … vu_9

/vu/5 … /vu/8

speakers 1–4

the lightning of each speaker

vu_10 … vu_12

/vu/9 … /vu/11

–

unused

The inputs count from 1, the addresses from 0: vu_N arrives as /vu/(N-1). Patch with the OSC numbers in mind and every meter lands one channel across — and still looks plausible.

Where it runs and where its settings live

The beat-analyzer runs on the A³ Core machine as the systemd --user service beat-analyzer.service, started and stopped together with the rest of Core (it is part of a3-main.service). The a3-core package installs the unit and builds the program from the beat-analyzer checkout in the a3-system workspace.

Its settings are a .env file in its working directory, build/ in the beat-analyzer checkout. It reads, in this order, the first of:

  1. build/.env

  2. .env one directory up, in the checkout itself

  3. .env.example in the working directory

and with none of them, it sends to a single target on 127.0.0.1:9000. The template is .env.example in the checkout:

cp .env.example build/.env

The settings that matter most:

Setting

What it does

OSC_HOST_<name>=host:port

one target for /beat (and the meters, unless OSC_VU_<name> is set). As many as you like. The name motion is special: in INT mode that target does not get the relayed beat

OSC_VU_<name>=host:port

a separate port for that target’s meters, so /beat and /vu do not share a socket

OSC_PORT_A3MOTION

where /beat, /clockmode and /tap arrive. 7775

BPM_MIN, BPM_MAX

the tempo range the clock counts in. A tempo outside it is doubled or halved into it

PIONEER_DEVICE_NUM

its player number on the Pro DJ Link network. 7

NUM_VU_CHANNELS

how many meters. 12

OSC_SEND_RATE

meter updates per second. 25

VU_RMS_ATTACK, VU_RMS_RELEASE, VU_PEAK_FALLOFF

how fast the meters rise and fall

DEBUG_BEAT_CONSOLE, DEBUG_PIONEER_CONSOLE

print every beat, or every Pro DJ Link beat, to the log

The settings are read at start. After a change, restart the service:

systemctl --user restart beat-analyzer

The clock mode is not a setting. The beat-analyzer always starts in mode 1 (intern) and changes when it is told to.

Which port on which device gets what is listed, as measured on the rig, in Ports and endpoints. The messages themselves are in the OSC reference.

Troubleshooting

Symptom

What to do

A³ Motion reads PIO or EXT, but the tempo follows the wrong source

The beat-analyzer restarted, or started after A³ Motion, and is back in its start mode (intern). Tap Motion’s clock key once round, back to the mode you want: every step tells the beat-analyzer again

EXT: no beat, the BPM stands still

Is the service running (systemctl --user status beat-analyzer)? Is bpm_1 connected in qjackctl? Is music reaching REAPER?

EXT: half or double your tempo

Set BPM_MIN–BPM_MAX to one octave around the music, for house and techno e.g. 70–140. A wider range lets the clock count either one

EXT: the tempo no longer follows the track

You tapped: a tapped tempo stays. Tap the new tempo, or restart the service

PIO: nothing arrives

The Core machine has to be on the same network as the players, and nothing else on it may hold ports 50000–50002 exclusively. The log says Pioneer Receiver konnte nicht gestartet werden if it could not bind them

PIO: it follows the wrong player

It follows whoever says master while playing. Set master on the player you mean

The meters all sit one channel across

The JACK patching is off by one: vu_N is /vu/(N-1)

The meters don’t move at all

Check the service, then the OSC_VU_* / OSC_HOST_* entries in build/.env against Ports and endpoints

Its log is the service’s journal:

journalctl --user -u beat-analyzer -f

With DEBUG_BEAT_CONSOLE=1 it prints a line per beat with the tempo and how far the beat was off; with DEBUG_PIONEER_CONSOLE=1, a line per Pro DJ Link beat, naming the player and whether it is master.