macOS · Broadcast BWF stamp
TCFrameLock app icon

TCFrameLock

Stamp the start into the files. Insert at Timecode in the editor.

If you have multitrack recordings and an LTC track alongside them, TCFrameLock sets the Broadcast Wave start point from that LTC on every audio track. In your movie editor, Insert at Timecode or Spot reads that start and places the clips on the timeline. The audio is copied, not re-encoded.

Buy / download See the pipeline

What the app is for

You recorded several tracks, and one of them is Linear Timecode. You want those files on a movie timeline at the same place the camera was. TCFrameLock reads the LTC and writes that start into every audio track as Broadcast Wave. In the editor you Insert at Timecode so the new files start on the right frame.

Step 1

Drop the session

Your audio tracks plus the LTC. WAV or AIFF, or a whole folder. The app looks for the timecode track so you do not have to label it.

Step 2

It reads the LTC

That track is the clock that ran while you recorded. The app uses it to find one start timecode for the whole session. That start is the beginning of the files, so every track shares it.

Step 3

Insert at timecode

Each track comes back as a Broadcast WAV with that start already set. In the movie editor, Insert at Timecode or Spot reads that start and places the clip on the timeline. That is how they land on the right frame.

How the stamp is computed

This is the actual pipeline in the app: decode, rewind to sample 0, convert SMPTE to a sample count, then write Broadcast Wave metadata. The numbers below are a real worked example at 48 kHz / 24 fps.

A multitrack session, one track is the clock

Input

Drop WAV or AIFF. The app probes sample rate, channel count, and length, then streams the first 60 seconds of every channel looking for LTC. Music can fake a sync word; a dedicated TC track is the usual source.

Mix_L.wav 48 kHz · 24-bit
MIX
Mix_R.wav 48 kHz · 24-bit
MIX
Dialogue.wav 48 kHz · 24-bit
MIX
Session_LTC.wav LTC on channel 1
LTC

Decode until the clock is unmistakable

libltc 1.3.2

LTC is Manchester biphase in the audio. The decoder is created with audio samples per video frame = round(sampleRate / nominalFPS). Isolated sync-word hits in music are ignored. Lock requires eight consecutive frames whose frame-count-since-midnight increases by exactly 1.

01:00:00:03
01:00:00:04
01:00:00:05
01:00:00:06
01:00:00:07
01:00:00:08
01:00:00:09
01:00:00:10

First confident frame

HH:MM:SS:FF = 01:00:00:10
sampleOffset = 48,000

sampleOffset is libltc’s frame.off_start, the sample in the file where that decoded frame begins.

Signal hints

apv ≈ round(48000 / 24) = 2000
dfbit · observed FPS · max FF

If the picker does not match the signal (23.976 vs 24, NDF vs DF), the app warns and offers the suggested rate. It does not silently switch.

The UI shows sample-zero timecode, not the first hit

Back-calculation

Recordings rarely start exactly on the first decoded frame. TCFrameLock walks the clock backward so the stamped address is “what SMPTE said when sample 0 was recorded.”

00:59:59:10 sample 0
01:00:00:10 first decoded LTC

Formula

samplesPerFrame = sampleRate / nominalFPS = 48000 / 24 = 2000
framesToSubtract = round(sampleOffset / samplesPerFrame) = round(48000 / 2000) = 24
sampleZeroTC = 01:00:00:10 − 24 frames = 00:59:59:10

Drop-frame uses SMPTE 30-family counting (drop 2 frames every minute except every 10th). A manual HH:MM:SS:FF override skips decode and uses your typed address instead.

BWF does not store HH:MM:SS:FF. It stores samples since midnight.

EBU Tech 3285

Time Reference is a 64-bit unsigned integer at byte 338 of the bext chunk. Each mix file is stamped at that file’s sample rate, so two mixes at different rates still share the same start timecode.

00HRS
:
59MIN
:
59SEC
:
10FRM

24 fps · DECODED · sample 0

Formula

totalFrames = frameCountSinceMidnight(00:59:59:10) = 86,386
seconds = 86386 / 24 = 3599.4166…
timeReference = round(seconds × mixSampleRate) = 172,772,000

Units: PCM samples since 00:00:00:00 at the output file’s sample rate. Same SMPTE start, different integer if a mix is 96 kHz instead of 48 kHz.

Inject bext, copy the audio, verify the integer

Non-destructive write

The writer streams a temp WAV, places bext immediately after fmt (EBU ordering), copies the data chunk in 1 MB buffers, atomically renames, then re-reads Time Reference. RF64 / files over 4 GB are refused. Source files are never overwritten.

RIFF

WAVE container. Size rewritten after the new bext is inserted.

fmt

Original format chunk. Linear PCM only. Copied as-is.

bext

Originator TCFrameLock. timeReference 172772000 at offset 338. Existing bext fields are preserved if the file already had one.

data

PCM copied verbatim. No resample, no dither, no transcode. That is the mix you already printed.

Output name: Mix_L_TC_143022.wav. If that name is taken, the app adds -2, -3, and so on. Reveal in Finder when the run finishes.

1. Bring the session

Multitrack files plus the LTC that was recorded with them. Drop the files or a folder.

2. It reads the LTC

That track is the clock that ran with the recording. The app uses it to find one start timecode for the whole session, then that same start is what gets written onto every audio track.

3. It stamps every track

Each track gets a new Broadcast WAV with that start written in. Same audio. The LTC file is not rewritten.

4. Insert at timecode

Bring the new files into your movie editor. Insert at Timecode or Spot puts each clip on the timeline at the right frame.

Specs

PlatformmacOS 14 or later, sandboxed native SwiftUI app
InputsWAV (RIFF) and AIFF / AIF, linear PCM
OutputsBroadcast WAV with bext; filename *_TC_HHmmss.wav
Frame rates23.976 NDF, 24, 25, 29.97 NDF, 29.97 DF, 30
Time ReferenceEBU Tech 3285, UInt64 little-endian at bext offset 338
OriginatorTCFrameLock, plus stamp date/time when creating a new bext
Not supportedRF64, compressed audio, files that would exceed the 4 GB RIFF limit
NetworkNone. Files never leave the Mac.

Built for the way broadcast files actually work

No re-encode on stamp

Native WAV PCM is streamed through unchanged. You are adding or relocating metadata, not printing a new mix.

LTC file stays a clock

The decoded track is the source of truth for the session start. It is not written. Only the audio tracks are stamped.

Streaming, not RAM-bound

Channel decode and BWF writes are chunked. Multi-gigabyte mixes do not get loaded twice into memory.

Verify after write

The output is opened again and Time Reference is read back. A mismatch is a failed file, not a silent bad stamp.

Correct DF and fractional rates

nominalFPS is the true rate (24000/1001, 30000/1001). Display digits stay 24 or 30. The two are not confused.

Local only

No account, no upload, no analytics in the app. Processing is a file in, a file out, on your disk.

Buy / download

Pay once for a personal or studio license. Questions go to the email below.

Support

support@stackcommander.com

Product questions, license questions, and anything the app points you to this site for.

License

When you pay, you get a license to use TCFrameLock on Macs you own or control, for personal or studio work. You may not copy, share, or resell the app. TCFrameLock itself stays proprietary; you may replace the bundled libltc under its LGPL terms. Publisher: Stackcommander LLC.

Refund policy

If something is wrong with the purchase or the download, email support@stackcommander.com. Our order process is conducted by our online reseller Paddle.com. Paddle.com is the Merchant of Record for all our orders. Paddle provides all customer service inquiries and handles returns. Full page: refund policy.

Privacy

The app does not upload files or analytics. Processing is on your Mac. Privacy policy.

Requirements

macOS 14 or later.

Third-party software

TCFrameLock uses libltc (LGPL). Licenses and source are in TCFrameLock → About TCFrameLock.

Common questions

What does TCFrameLock do?

If you have multitrack recordings and an LTC track recorded with them, TCFrameLock sets the Broadcast Wave start on every audio track from that LTC. In your movie editor, Insert at Timecode or Spot reads that start and places the clips on the timeline. The audio itself is not re-encoded.

What is a Broadcast WAV Time Reference?

In the EBU bext chunk, Time Reference is a 64-bit integer: PCM samples since midnight (00:00:00:00) at the file’s sample rate. NLEs use it to place sample 0 on a known SMPTE address. The app does not write a human-readable HH:MM:SS:FF string as the alignment value. It writes the sample count those systems expect.

Does it re-encode the audio?

No. A native WAV is stamped by injecting or updating bext and copying the data chunk. AIFF is converted to a working WAV first so the rest of the pipeline can run; the original AIFF is left alone.

Does it change the LTC file?

No. The LTC source is read only. Audio tracks are written as new timestamped WAV files. Existing files are never overwritten.

What if two files both look like LTC?

The session is marked ambiguous. You pick the LTC source in the UI, or right-click a file and assign it. If nothing locks, you can still type a manual start timecode.

Which frame rates are supported?

23.976 NDF, 24, 25, 29.97 NDF, 29.97 drop-frame, and 30. Changing the picker re-analyzes the files. A mismatch with the LTC signal is a warning, not a silent rewrite.

Is this a subscription?

No. You pay once for a personal or studio license. See Buy / download or email support@stackcommander.com.