Docs

Docs Reference

NMC, NAP and .nfa

This page summarises the three pieces NOT Cable developed itself. All of them were written by notFM; no off-the-shelf codec was taken and a network built around it.

All specifications are public: github.com/emrehakan-ai/notcable. The implementation is not open source.

NMC#

notFM Media Codec. A music codec designed not merely to compress audio but to play it timed and synchronized across a network.

Synchronization-first frames. Every frame is a timing-predictable unit, not just audio bytes. A receiver always knows how many samples it carries, when it must play, and how to recover if it is lost.

Independently decodable. Every frame decodes on its own and carries its own checksum. A corrupted frame is not played silently; it is identified.

Tuned for store music. It does not aim at film, gaming or telephony. It is tuned for long listening sessions, low fatigue, low stable bitrates, continuous broadcast and clean announcement transitions.

Heavy encoder, light decoder. Encoding happens once, on a strong machine or at import time. The decoder has to stay light enough to run comfortably on palm-sized boards. Installing a hundred points must not mean buying a hundred expensive machines.

NAP#

notFM Audio Protocol. The network protocol that carries audio packets and the shared timeline.

Arrival time and playback time are separate. A receiver gets packets ahead of time, places them in a jitter buffer and schedules them against the common timeline. That separation is the heart of the protocol.

Fixed header, integrity check. Every audio packet carries a fixed 48-byte header, the NMC frame and a 4-byte checksum trailer.

0 magic 4 ver 5 tip 6 hdr 8 flags 12 stream id 20 seq 24 playback time 32 rate 36 ch 38 mode 40 pcm 42 rsv 44 len 48 NMC frame CRC32
A NAP audio packet. The whole sync model sits in the two highlighted fields.

A separate clock channel. Clock request and response packets flow independently of audio. The clock keeps running even when the music stops, so a track that starts hours later still starts in sync.

Sent once, received by many. The broadcast goes out as multicast. The source sends each packet once and the network delivers it to every joined receiver.

Control packets travel over the same protocol. The receiver kick and ban commands are among them.

.nfa#

notFM Audio Stream. The broadcast-ready file format. Inside it sits a sequence of independently decodable NMC frames.

Encoded once, ready every broadcast. The file is encoded once at import. At broadcast time the source puts the stored frames straight into network packets, with no re-encoding.

Same file, same result. Because nothing is re-encoded, every broadcast of the same file is bit-identical and costs no encoder CPU at play time.

A self-describing header. The header states the codec mode, sample rate, channel count, target bitrate, frame count and total sample count. The header itself is protected by a checksum.

The processing chain#

The broadcast chain runs in the same place, at the source, and is applied before NMC encoding. What goes onto the network is already processed audio.

See Audio processing for detail.

Byte layout#

The following comes from the public specification. Multi-byte integers are big-endian in NAP packets and little-endian in .nfa files. Both use the same CRC32 polynomial, 0xEDB88320, reflected.

NAP audio packet, header 48 bytes:

offset  size  field
0       4     magic "NAP1"
4       1     protocol version (1)
5       1     packet type
6       2     header size
8       4     flags (bit 0: end of stream / track boundary)
12      8     stream id
20      4     sequence number
24      8     playback time, nanoseconds on the shared timeline
32      4     sample rate
36      2     channels
38      2     codec mode
40      2     PCM frames carried
42      2     reserved (0)
44      4     payload byte count
48      n     NMC frame payload
48+n    4     CRC32 of bytes 0..48+n-1

Packet types: 1 audio, 2 clock request, 3 clock response, 4 control.

.nfa header:

offset  size  field
0       4     magic "NFA1"
4       2     container version (1)
6       2     codec mode
8       4     sample rate
12      2     channels
14      2     reserved (0)
16      4     nominal target bitrate, bits per second
20      4     frame record count
24      8     total PCM frames
32      4     CRC32 of header bytes 0..31

The clock#

Clock synchronization uses a four-timestamp exchange. The request is 32 bytes and the response 48, and both carry the request id and the timestamps.

A receiver runs one exchange per second, fits clock offset and drift over a sliding window, and weights low round-trip observations sharply higher. A jittery exchange over wireless therefore fades out of the estimate instead of biasing it.

Track changes#

A new track is announced as a higher stream id on the same timeline. There is no separate command, no handshake and no re-locking. Receivers in session mode adopt the new id as it comes.