Skip to content

Super Timecode Converter V1.8.1

Choose a tag to compare

@fiverecords fiverecords released this 28 Mar 21:28
· 17 commits to main since this release
04e7778

Real-Time Audio BPM Detection

STC can now detect BPM in real time from any audio input, filling a gap for non-DJ input sources (MTC, LTC, Art-Net, System Time) where no CDJ or Denon hardware provides BPM data.

The detected tempo is forwarded to all BPM outputs -- MIDI Clock, OSC BPM, and Ableton Link -- exactly as CDJ/Denon BPM is forwarded in Pro DJ Link and StageLinQ modes.

How it works:

Audio BPM uses the BTT library (Beat-and-Tempo-Tracking by Michael Krzyzaniak, MIT License) to perform spectral flux onset detection, autocorrelation-based tempo estimation, and beat prediction -- all in real time from the audio callback. It processes mono audio and produces a BPM estimate that converges within a few seconds of hearing music.

Configuration:

  • Enable "AUDIO BPM" in the engine panel (visible when input is MTC, LTC, Art-Net, or System Time)
  • Select an audio input device and channel from the audio settings controls
  • When the engine input is LTC, Audio BPM shows its own separate device/channel/gain controls (since LTC owns the shared audio settings section)
  • When the engine input is any other non-DJ source, Audio BPM shares the AUDIO SETTINGS section (driver filter, sample rate, buffer size, device, channel, gain, meter)
  • The detected BPM appears with a live beat LED indicator and colour-coded confidence display

BPM Display:

  • Green: confidence > 60% -- tempo locked, reading reliable
  • Orange: confidence 30-60% -- actively tracking, adjusting
  • Dim orange: confidence 15-30% -- detecting but uncertain
  • Grey "--- BPM": no detection (silence or below confidence threshold)
  • Beat LED flashes at the detected BPM rate

BPM Smoothing:

A "BPM SMOOTHING" slider (0-100%) controls how quickly the BPM reading reacts to tempo changes:

  • 0% = fast tracking (reacts immediately, may fluctuate)
  • 50% = balanced (default)
  • 100% = very stable (slow to react but rock-solid reading)

Smoothing operates at two levels: an EMA (exponential moving average) on the output, and BTT's internal Gaussian tempo histogram parameters (decay and width). Both are tuned simultaneously from the single slider.

BPM Output Routing:

When Audio BPM is active, BPM output toggles (MIDI Clock, OSC Tempo, Ableton Link) appear inline within the AUDIO BPM section -- no empty section headers cluttering the UI.

Typical use case: A DJ plays from vinyl, CDJ without Pro DJ Link, or a MIDI controller. The venue's audio feed goes into an audio interface. STC receives LTC timecode on one channel for show cue synchronization, and analyses the audio on another channel (or the same interface) for BPM. Resolume, lighting desks, and other tools receive both timecode and tempo.

Design decisions:

  • Audio BPM runs on its own AudioDeviceManager, independent of the LTC input device.
  • When a DJ source (Pro DJ Link / StageLinQ) is active, audio BPM is not available -- protocol BPM is always more precise.
  • BTT is tuned for DJ/electronic music: tempo centre 128 BPM, range 60-200 BPM.
  • A confidence threshold (15%) prevents spurious values during silence or speech.
  • Device in-use markers show which engines are using which audio devices for BPM (same pattern as LTC markers).

OSC Command Template (GMA3 Support)

The OSC BPM forward now supports a command template for consoles that receive BPM as a string command rather than a float value.

A new "CMD" field appears below the OSC address when OSC Tempo is enabled. When the CMD field is empty (default), STC sends a standard OSC float -- compatible with Resolume and most OSC receivers. When CMD contains text, STC sends it as an OSC string argument with %BPM% replaced by the current BPM value.

GrandMA3 example:

  • Address: /gma3/cmd
  • CMD: Master 3.x at %BPM%

STC sends: /gma3/cmd with string argument "Master 3.x at 128.5"

Resolume (default, no change needed):

  • Address: /composition/tempocontroller/tempo
  • CMD: (empty)

STC sends: /composition/tempocontroller/tempo with float argument 128.5

The template works with all BPM sources (Pro DJ Link, StageLinQ, Audio BPM).


Ableton Link Exclusivity

Ableton Link is now exclusive per engine. Only one engine can have Link active at a time.

  • If Engine 1 has Link active and you try to enable it on Engine 2, the toggle reverts and shows "Link active on Engine 1" in red.
  • When viewing an engine without Link, the status label shows "Active on [Engine X]" in grey if another engine owns it.
  • Link is no longer propagated via global settings -- each engine's Link state is independent.
  • Settings restore guards ensure only the first engine with linkEnabled=true activates Link (protects against legacy settings from pre-v1.8.1 where Link was propagated to all engines).

PDL View Responsive Layout

Redesigned the per-deck layout in the Pro DJ Link View to scale properly at any window size.

Before: All sections (info, preview waveform, detail waveform, timecode) used proportional height allocation (flexH * 0.28f, etc.). At small window sizes, every section received too little space simultaneously -- text became microscopic and lower rows (beat indicator, track time) disappeared completely even with space available.

After: Priority-based layout with fixed minimum sizes:

  • Info section uses fixed 14px line heights -- text never shrinks below readable size
  • Bottom chrome (map row, engine row, BPM multiplier) uses fixed 16px rows that hide progressively on very small decks (< 120-160px)
  • Waveforms get whatever space remains after info + chrome
  • Detail waveform hides first when space drops below 80px, freeing room for preview waveform and timecode
  • Beat indicator and track time rows appear only when there's room, instead of always taking space

The result: at normal sizes everything looks the same, but shrinking the window now degrades gracefully -- detail waveform disappears first, then bottom chrome, while text stays readable throughout.


Bug Fix: Tracks Without Artist

Fixed: tracks with no artist metadata were blocked from Learn, TrackMap lookup, waveform/artwork caching, cue point auto-populate, and BPM multiplier persistence.

The root cause was hasValidKey() requiring both artist and title. Since the TrackMap key is artist|title[|duration], an empty artist produces a valid key like |my track title|300 -- unique and functional.

18 guards fixed across 7 files:

  • AppSettings.h: hasValidKey() now only requires title
  • TrackMapEditor.h: Learn button works without artist
  • TimecodeEngine.h: lookupTrackInMap() and refreshTrackMapLookup()
  • ProDJLinkView.h: BPM save, TrackMap lookup, waveform cache, artwork cache, cue point auto-populate, ANLZ save (6 fixes)
  • StageLinQView.h: TrackMap lookup during playback
  • DbServerClient.h: disk cache key generation for ANLZ/waveform (4 fixes)
  • MainComponent.cpp: BPM multiplier button state, CuePoint editor artwork lookup, CuePoint playhead matching, BPM mult save to TrackMap (4 fixes)

BTT Library Integration

The BTT library (ANSI C, zero external dependencies, MIT License) is integrated as a single-file amalgamation, following the same pattern as sqlite3:

  • btt_build.cpp -- the only file added to the Projucer (C++ wrapper with MSVC warning suppression and macro isolation)
  • btt_amalgamation.inc -- all BTT source files concatenated with extern "C" linkage (not added to Projucer)
  • BTT.h -- standalone public API header
  • BTT_LICENSE -- MIT license (Michael Krzyzaniak, 2021)

MSVC compatibility: VLA replacement with fixed arrays, M_PI define, random() -> rand(), explicit casts for calloc/enum/void*, #undef real/imag to neutralize <complex> macros from JUCE PCH.


New Files

File Description
BTT.h Standalone BTT public API header (no subfolder dependency)
btt_build.cpp C++ wrapper -- only BTT file added to Projucer
btt_amalgamation.inc Full BTT library amalgamation (included by btt_build.cpp)
BTT_LICENSE MIT license (Michael Krzyzaniak, 2021)
AudioBpmInput.h Audio BPM detection class with EMA smoothing

Modified Files

File Change Summary
TimecodeEngine.h Audio BPM member + start/stop/getters; sendBpmOsc() helper with template support; oscFwdBpmCmd member; setOscForward() 3-param signature; tick forwarding for non-DJ sources; Link not force-disabled when audio BPM active
TriggerOutput.h Added sendOscString() method for OSC command template
AppSettings.h New fields: audioBpmEnabled, audioBpmDevice, audioBpmType, audioBpmChannel, audioBpmSmoothing, audioBpmGain, oscBpmCmd; hasValidKey() fix
MainComponent.h New widgets: BeatLed class, lblBpmValue, ledBeat, sldBpmSmoothing, sldBpmInputGain, edOscFwdBpmCmd/lblOscFwdBpmCmd; findLinkOwnerOtherThan() method; beat flash timing state
MainComponent.cpp Full Audio BPM UI (toggle, BPM display, beat LED, smoothing, gain, device combos); shared vs separate audio settings for LTC mode; inline BPM output layout; OSC command template UI; Link exclusivity; device in-use markers for Audio BPM; artist bug fixes (4); settings save/load/restore for all new fields
ProDJLinkView.h Priority-based deck layout (fixed line heights, progressive hiding, detail waveform collapses first); artist bug fixes (6)
StageLinQView.h Artist bug fix: TrackMap lookup
DbServerClient.h Artist bug fixes (4): disk cache key generation
TrackMapEditor.h Artist bug fix: Learn button
Main.cpp Version 1.8.1
SuperTimecodeConverter.iss Version 1.8.1