Skip to main content
The analog file describes segments, not samples. Each row is a whole curve segment, and the generator rebuilds it. A file of dozens of lines instead of tens of thousands.

Structure

Nine columns: A straight segment —an undeformed chord— carries - in Handle_X, Handle_Y and Radius.

How it is ordered

The rows are ordered by the step they start at, mixing every channel: it is the order in which it plays back.

Each row stands on its own

A row says from which step to which step it runs, on which channel, between which levels and with what curve. The arrival level repeats as the starting level of the next row, and that repetition is exactly what saves you from remembering old rows from other channels. The result: you can play it back one line at a time, without loading the whole file into memory.

The only column that looks ahead

Corner_Radius says how much to round the break with the segment that follows on that same channel:
  • With - or 0, the break stays sharp.
  • With a radius r, the curve eats the last half of r of this segment and the first half of the next, passing through the connection point as a vertex.
The last segment of a channel has no next one, so it forms no corner: it carries -.

What is not in the file

There is no total length. The analog signal lasts as long as its segments and can end before the end of the timeline.
A channel with fewer than two connection points describes no segment —with no duration there is no signal to recreate— so it is left out of the file.

The resolution

Level0 and Level1 come out quantized to the resolution chosen on export: 8, 10, 12 or 16 bits.
The ESP32 DAC is 8-bit (0–255) and tops out near 3.3 V. If you exported at a higher resolution, you have to rescale when playing back.

With metadata

At the end of the file, after a blank line:
The playback example, reading from a microSD card, is in Generate the signal with an ESP32.