Open Audio Analyzer

Metrics

What every number means, how it is computed, and whether this build measures it.

Every quantity Open Audio Analyzer displays, with its definition and where that definition comes from. A metric that appears in the UI without an entry here is a number nobody can verify, which is the same as a number nobody should trust.

Availability says whether the current build measures it. Anything not measured is NaN in the snapshot, carries a OAA_FLAG_*_UNAVAILABLE flag, and renders as an em dash — never as a zero.


Loudness

Metric Unit Definition Availability
LUFS-M LUFS Mean K-weighted loudness over a sliding 400 ms window. ITU-R BS.1770-4 §2, EBU Tech 3341. now
LUFS-S LUFS Same, over 3 s. now
LUFS-I LUFS Gated integrated loudness since reset. 400 ms blocks at 75% overlap; absolute gate −70 LUFS; relative gate 10 LU below the ungated mean of the surviving blocks. ITU-R BS.1770-4 §3. now
LRA LU Loudness range. Distribution of 3 s short-term values, gated absolutely at −70 LUFS and relatively at −20 LU, then the 95th percentile minus the 10th. EBU Tech 3342. now

Both gated distributions are histograms of 0.01 LU per bin holding exact energy sums — 8000 bins over the useful range — rather than a growing sorted list. That is O(1) per update in constant memory, which is what makes an integration that runs for hours cost the same as one that runs for seconds, and the bin is an order of magnitude finer than the ±0.1 LU the standard asks the answer to be within.

The 120-bin histogram published in the snapshot is a different, coarser thing — it is for drawing, spans −60 to 0 LUFS at 0.5 LU, and is finer than a pixel column on any real display. It is taken from the same population as the LRA number, so a distribution drawn from it cannot disagree with the readout beside it.

The Loudness Distribution module draws it, bracketed between the two percentiles with LRA printed on the bracket — see lib/src/modules/loudness_distribution.dart. Every bin is drawn at the height it was published; where the module is narrower than 120 pixels a column takes the loudest bin it covers rather than their mean, which is the same choice, for the same reason, that the engine makes mapping transform bins into spectrum bands: a mean at a coarser resolution hides a spike, and a spike here is a section of the programme that sat at one level.

Note that the Histogram module is a different picture of the same measurement: short-term loudness against time rather than against how often. Only one of the two names is literally a histogram; both are the names these displays are known by, so both are kept.

The Histogram draws an average of its two bands rather than each 50 ms column as measured, and says which in its own menu: Smoothing is Off (no averaging), Light (0.5 s), Normal (1.0 s) or Broad (2.0 s), and Normal is the default. Both bands take the same window, because the gap between them is the reading and smoothing one of them would make that gap a difference between two filters. The window is centred, not trailing: the module draws history, so a lagging filter would slide the whole curve along a time axis labelled in seconds before now and be wrong about when — what a symmetric window costs instead is that the newest column, which has no future yet, is an average of the newest half-window and settles as it ages. Nothing goes past 2 s, because short-term loudness is a 3 s window already and a smoother approaching it draws the momentary band and the short-term curve as one line.

The measurement is untouched by any of it: the module’s ring holds the columns as they were measured and the averaging is applied when they are read, so the setting redraws the whole programme so far and Off is the measured columns exactly. LUFS-M, LUFS-S and every other module reading them are unaffected.

K-weighting is the BS.1770-4 two-stage filter: a high-frequency shelf followed by an RLB high-pass. Coefficients are computed from the analog prototype at the stream’s actual sample rate, not read from a 48 kHz table, so 44.1, 88.2, 96 and 192 kHz are correct rather than approximately correct.

Channel weights are BS.1770-4: L, R, C at 1.0, and the surround pair at 1.41 (+1.5 dB). The LFE channel is excluded from loudness, as the standard requires. Everything past 5.1 is unweighted — the rear surrounds of a 7.1 layout weigh the same as the front, which is what Report ITU-R BS.2217’s channel table states and what its two 7.1 files measure; weighting them 1.41 read those files 0.35 LU high.

An interleaved buffer does not say which channel is which, so the layout is inferred from the channel count — see oaa_channel_weight for the table. The four-channel case is read as quad (L R Ls Rs) rather than L R C LFE, because mistaking a surround channel for LFE would silently drop real content from the measurement. When a device or file source supplies a real channel layout, that should replace the inference.

Peak

Metric Unit Definition Availability
True Peak dBTP Maximum inter-sample peak over a sliding 3 s window. ITU-R BS.1770-4 Annex 2: 4× oversampling with the specified 48-tap polyphase FIR (12 taps per phase). now
TP Max dBTP Same, maximum since reset. now
Peak dBFS Highest sample magnitude, with the meter’s hold and fall applied. Default hold 1.5 s, fall 20 dB/s. now
Peak Max dBFS Highest sample magnitude since reset, unheld. now
RMS dBFS Root mean square, smoothed in the mean-square domain with a 300 ms one-pole. now
Clip samples Longest run of consecutive samples at or above 0.999 since the last reset, per channel. Latched: non-zero means this channel clipped and stays non-zero until Reset. Drawn as the Digital Meter’s clip lamp. now

Sample peak and true peak differ, and the difference is the point: a signal can sit at −0.1 dBFS and still reconstruct above 0 dBTP after conversion. Only true peak is checked against a delivery ceiling.

Oversampling is 4× at every sample rate. Above 96 kHz the standard allows 2×, but that needs a second filter design to be correct, and 4× is never less accurate — only more work, and not enough of it to notice.

Dynamics

There is no standard that says what “dynamic range” is. Analysers in this class each report a figure of their own, and the one this project is modelled on calls its TrueDyn and defines it nowhere anybody outside can read. Open Audio Analyzer defines Open Dynamic Range instead — ODR-S over the last three seconds and ODR-I over the programme — and the definition is a document of its own: ODR.md, normative and versioned, with the conformance cases that hold an implementation to it. This section is the product’s view of it; where the two differ, the specification is right.

Metric Unit Definition Availability
Crest dB Sample peak minus RMS, both over the same block — the block’s own values, not the held peak and smoothed RMS the meters draw. For a sine this is exactly 3.0103 dB and for DC it is 0. Multichannel reports the peakiest channel rather than the loudest peak minus the loudest RMS, which could describe no channel at all. now
PSR, or ODR-S LU Open Dynamic Range, short-term: TruePeak − LUFS-S, both over the same sliding 3 s window. Undefined — NaN, drawn as a dash — while LUFS-S is at or below the −70 LUFS absolute gate. ODR § 4. Printed as PSR unless the setting says otherwise; see The name below. now
PLR, or ODR-I LU Open Dynamic Range, integrated: TruePeakMax − LUFS-I, both since the last reset. Undefined for as long as LUFS-I is; the peak is gated by nothing. ODR § 5. Printed as PLR unless the setting says otherwise. now

In one paragraph, so that this table can be read without the specification: the peak is true peak, the loudest channel’s, never sample peak; the loudness is BS.1770-4’s, ungated for LUFS-S and gated for LUFS-I; both operands of ODR-S cover the same three seconds; both readings are undefined rather than zero where there is no programme; the unit is LU at 0.1; and neither reading moves when a platform turns the master down. A stereo 1 kHz sine reads exactly 0.0 LU on both, in mono 3.01 — the crest of a sine, the second channel and the K filter’s gain at 1 kHz cancel to nothing — and packages/oaa_engine/test/conformance_test.dart asserts every case in ODR § 7.

Where the product shows them. ODR-S and ODR-I — printed as PSR and PLR by default — are Number Box and Alert Meter metrics; the Super Meter draws them as arcs continuing from each loudness arc’s tip to the true peak — stacked on the same dB scale, so the dark rest of the ring is the true peak’s headroom — and prints ODR-S in the lane inside its arc and ODR-I beside the integrated loudness in its centre; a file report states ODR-I and the minimum ODR-S of the programme (ODR § 4.5), the most squeezed three seconds; and a delivery target may set a floor on either, odr_i_min and odr_s_min, each of which is a line of the Validator, the report and the oaa verdict — the ODR-S line judged against the minimum, which the Validator keeps since the last reset. The text report prints ODR-I’s band word after the reading — (balanced) — from ODR Annex A, in the human format alone, never the JSON; and one built-in target, Dynamic master, carries the annex’s 8 LU floor on the minimum ODR-S, the one built-in that is a recommendation rather than a platform. Through 0.14.0 ODR-S read a number in silence; see the changelog.

The name. The product prints PSR and PLR unless told otherwise — the names the AES gives this arithmetic, which every other meter prints and which a person types into a metric picker — and Settings › Dynamics switches every label to the specification’s own ODR-S and ODR-I: on each module, in the report, in the target editor, and on a paired tablet, which is sent the choice beside the skin and the target. Nothing but the label moves; the oaa CLI has the same switch as --names. The two spellings are one measurement and are never shown together, per ODR § 6.4. The pair went through four names to get here: PSR / PLR and DR-S / DR-I through 0.14.0, ODR-S / ODR-I alone in 0.15.0, which nobody searching for PSR could find. DR stays retired, because that is what the offline TT Dynamic Range meter calls its number, a different measurement with a different algorithm, and a reader who knows that meter would take DR-I for it. Open Audio Analyzer does not report the TT figure under any name. A Number Box saved on psr, plr, dr_s or dr_i opens on the same reading, and a report’s JSON carries odr_i and odr_s_min whatever the labels say. What ODR is and is not, measure by measure — the AES pair, TrueDyn, DR, LRA, crest — is ODR § 8.

What a value means. High, low, crushed, wide — the interpretation is ODR Annex A, informative and kept apart from the definition so the guidance can move without the measurement moving. The short version: after a platform normalises a master, its true peak lands at the platform’s target plus the master’s ODR-I — so 13 LU is the most a −14 LUFS platform can play at its target — and the one published perceptual floor is 8 LU on the minimum ODR-S.

Stereo field

Metric Unit Definition Availability
Correlation — Pearson correlation of L and R over the block, then a 200 ms one-pole so it is readable. +1 identical (mono), 0 uncorrelated, −1 polarity-inverted. Gated — see below. now
Balance — (E_R − E_L) / (E_R + E_L) where E is block energy. −1 hard left, 0 centred, +1 hard right. Gated — see below. now

Mono sources report correlation +1 and balance 0. Saying so is more useful than reporting nothing, and it is also true.

Both are gated at −70 LUFS, R128’s absolute gate, applied per channel to the block’s unweighted mean square. Correlation needs both channels above it and balance needs either: a hard-panned source has nothing in one channel to correlate however loud the other one is, and which side it is on is exactly what balance is for. Under the gate each reads as a dash.

Both quantities divide by the channels’ energy, so with nothing there they are 0/0, and 0 — “uncorrelated, dead centre” — is a reading nobody took. For correlation it is worse than merely invented: a one-pole approaches its target asymptotically and never reaches it, so a substituted 0 leaves the published value carrying the sign of the last audio for as long as the silence lasts. A track that fades out on a wide reverb tail ends slightly out of phase, and the Phase Scope then held its correlation marker off centre and lit it in the warning colour — asserting anti-phase content in a signal that had stopped — until the exponential underflowed some twenty seconds later.

A gate rather than a guard against dividing by zero, and the difference is the whole point: a live input is never exactly zero. It sits on a converter’s noise floor, and the correlation of two channels of noise is a random number near zero whose sign falls whichever way the block did. A threshold at float underflow answers honestly for a stopped software player and goes on reporting dice rolls for a desk with nothing playing into it.

The first block of audio after silence, and after a reset, seeds the smoother instead of mixing with it — the smoothed value is its own state, and NaN mixes to NaN for ever.

The two displays that plot the stereo field do not draw it, though. The raw sample stream a goniometer reads is built the same way the spectrum’s pan is — channel 0 is copied into the right slot of every frame when there is only one channel — so a one-channel source is L == R exactly, and the Phase Scope rotates that into a hard, perfectly straight vertical line that never moves. It is a true picture of a tautology and it is indistinguishable from a display that has stuck, which is what the Stereo Cloud’s version of it was reported as. Both say MONO SOURCE across the face instead and leave their graticule drawn. The correlation and balance markers on the Phase Scope’s frame are withheld for the same reason: a marker pinned at the mono end of its edge is the same tautology one stroke over. They are withheld under the gate too, by the ordinary NaN rule — a marker is a reading, and there is none. The numbers themselves are still measured and still available — a Number Box set to Correlation or Balance prints them, and so does an offline report.

Spectrum

Metric Unit Definition Availability
Spectrum dBFS 512 log-spaced bands from 20 Hz to 20 kHz. A 4096-point Hann window per channel at a 1024-sample hop, zero-padded to a 16384-point transform. A band wide enough to contain bins takes the loudest bin in the band rather than their mean, so that a narrow resonance survives the mapping; a band too narrow to contain one reads the transform between its two nearest bins. now
Spectrum peak dBFS Per-band hold, computed in the engine because a transform runs every hop and a publish carries only the last one. now
Spectrum pan — Per-band stereo position, −1 hard left to +1 hard right, as the energy balance (R − L) / (R + L) of the band’s power over the front pair. What the stereo cloud draws — through the pan pot’s angle rather than as the balance itself, see below. now, two channels or more
Spectrum · Left, Right dBFS The same bands, folded from one channel of the front pair alone, with the same loudest-bin rule and each with its own Spectrum peak. Left on a one-channel source is the combined set band for band. now; Right two channels or more
Spectrum · Mid, Side dBFS The same bands of (L + R) / 2 and (L − R) / 2, transformed as signals — so a signal identical in both channels reads its full level on Mid and nothing on Side, an anti-phase one the reverse, and a hard-left one −6.02 dB on both. Each with its own Spectrum peak. now, two channels or more

The Spectrum Analyzer draws an average of these bands rather than the last one published, and says which in its own menu: Response is Fast (no averaging), Normal (120 ms) or Slow (500 ms), and Normal is the default. The averaging is one pole per band on the dB value being drawn — a display ballistic, in the sense a VU movement is one, not a power average of the signal. The line above the curve is the envelope of that curve: the highest it has been, held for 1.5 s and then let down at 12 dB/s, which is the schedule the engine’s own Spectrum peak follows. It therefore moves with the curve instead of snapping to a peak the curve is still easing towards, and on a slow response it sits below a peak the programme really reached, because the curve it is holding never went there. Fast is the setting that catches a click.

Tilt in the same menu rotates the drawn curve about 1 kHz, at 0, 1.5, 3, 4.5 or 6 dB per octave, and 4.5 dB/oct is the default. It adds a fixed offset per band — nothing else — and exists because programme material falls with frequency at roughly 3 to 4.5 dB an octave, so an untilted analyser draws every mix as the same ramp and spends its height on the one part of the picture that carries no information. At 4.5 dB/oct the ends of the range are rotated 44.8 dB apart: 20 Hz is drawn 25.4 dB lower than it measures and 20 kHz 19.4 dB higher. The dB scale on the left is therefore true at 1 kHz and rotated away from it, which is why the module prints the tilt it is drawing at, and why 0 dB/oct — where the scale is true everywhere — prints nothing.

Range in the same menu sets how far below full scale that scale reaches: 60, 90 or 120 dB, and 90 dB is the default — the three values and the default Pro-Q’s analyser uses. The axis is linear over the range, labelled every 6, 10 or 12 dB, and the module prints the range in its top-right corner. It is the one level axis in the application that is not tapered, because a range setting on the tapered scale would move nothing but the bottom tenth of the plot. Like the tilt, it moves the picture and nothing else.

The measurement above is untouched by any of it: every set of bands and its peak is what the wire protocol carries whatever a module is set to, and every other module reading these bands — the spectrogram, the stereo cloud — draws them as published.

Source in the Spectrum Analyzer’s and the Spectrogram’s menus chooses which set: All is the combined bands — the loudest bin across every channel, which is what both drew before the setting existed and is deliberately not called a sum, because it is not one — and Left, Right, Mid and Side are the sets above. A set the signal cannot provide is not measured, and the module says MONO SOURCE rather than drawing the one channel twice. The setting is part of the module and travels with the layout, so a tablet shows the host’s choice.

Spectrum pan needs a front pair. A one-channel source reports every band at 0, for the same reason correlation reports +1 — mono is dead centre, and it is true. The stereo cloud does not draw that, because a column of centred bands is a bright vertical line down the middle of the display and is read as a broken module rather than as a mono signal; it says MONO SOURCE instead, as the Phase Scope does for the same reason — see Stereo field.

The stereo cloud places a band at the pan pot’s angle the balance implies, not at the balance itself: atan2(√R, √L) over the two channels’ shares of the band’s power, 45° at centre and the edges at 0° and 90°, so a source sits where a constant-power pan pot put it and a lean of three decibels is a fifth of the way over. The balance is steepest at the centre — three decibels is a third of the way to the edge on it, ten nearly hard against it — and drawn on that ruler every band of any width swept the plot from side to side. The published number is the balance; the ruler is the module’s.

Levels are window-compensated: a full-scale sine on a bin centre reads 0.0 dBFS, and that is asserted on every push. A tone between two bin centres reads within 0.3 dB of its own level, asserted likewise.

The window and the transform are different lengths and they answer different questions. The window is what the analysis can resolve: 4096 points is an 11.7 Hz main lobe at 48 kHz, and two tones closer together than that merge into one hump no matter what follows. The transform is how finely that lobe is sampled for drawing, and padding the window out to 16384 samples the same transform of the same audio every 2.93 Hz instead of every 11.7 Hz. Nothing is invented by it: a zero-padded DFT is the exact continuous-frequency transform of the windowed frame, read at four times as many frequencies.

That is also why the bands below about 216 Hz are allowed to read between two bins. The bottom octave of the display is 51 of the 512 bands spread across 20 Hz and no real-time transform puts a bin every 0.4 Hz, so rounding each band to its nearest bin drew the bass as a staircase. The bins on either side are not separate measurements with unknown territory between them — they are samples of one continuous curve, taken four to a main lobe, and a straight line between two of them is within about a tenth of a decibel of it. Frequency resolution is unchanged by any of this; only the sampling of it is finer.

The bands are unweighted (Z), and a weighted spectrum — A, C or any other — is not built, nor are selectable FFT sizes: the window is 4096 points. One set of transforms feeds the analyser, the spectrogram and the stereo cloud, so three modules cannot disagree about where a peak is.

One reading is A-weighted: the analyser’s cursor prints the band under it in dB(A), which is that band’s level plus the IEC 61672-1 A curve at the band’s centre frequency. That is exact for a band — a band is a level at a frequency, and weighting a component at a frequency is adding the curve’s value there — and the curve is a function of frequency alone, so it is computed in oaa_core (aWeightingDb) and held against the standard’s table to a tenth of a decibel. It is not an A-weighted loudness, which would be a sum over the weighted spectrum and which nothing here reports. The tag’s other two numbers are the drawn level and the drawn peak hold at the band — the two lines the cursor crosses — and all three are the measured level, not the tilted one: Tilt rotates the picture, and the cursor is where the untilted number can still be read off a tilted plot.

Conventions

  • The dB floor is −144.0, a little below the noise floor of 24-bit audio. Real -INFINITY is avoided because differences of dB values are meaningful here — crest is peak minus RMS — and -inf − -inf is NaN, which would turn a silent passage into “no data”. No dB reading is ever published below it, which is a stronger claim than “silence reads −144” and is the one that matters: a quantity that is merely usually floored will find the case where it is not. LUFS-M and LUFS-S clamped by testing against −infinity rather than against the floor, and the case that misses is the ordinary one — a K-weighting window holding nothing but the filters’ ringing, which is what every window holds for a moment after the music stops.
  • A level standing at the floor is displayed as -∞, not as -144.0. The floor is a clamp, so the number that reaches a readout for digital silence is a sentinel rather than a measurement, and printed to four significant figures it is precise, plausible and nobody’s reading — while the meter beside it labels that same end of its scale -∞ already. This is a rendering rule and nothing more: the snapshot, the wire and the JSON report all still carry −144.0, which is what keeps the differences above working. It applies to the eight absolute levels — LUFS-M, LUFS-S, LUFS-I, true peak, true peak max, sample peak max, peak and RMS — and to nothing else, because a range or a difference never reaches the clamp. Silence is a measurement, so it is -∞ and not the em dash, which stays reserved for a quantity nobody measured.
  • A delivery check is not answered by silence. True peak max is a running maximum, so unlike the gated quantities it carries a number — the floor — from the first block, and that number satisfies every ceiling anybody states. A true peak at the floor therefore counts as not measured in both places a verdict is given, the Validator’s table and the delivery report, rather than passing.
  • Reset clears every integrating quantity (LUFS-I, LRA, all Max values, the latched clip runs) and restarts the elapsed clock. Momentary values are left alone; they describe the signal, not the session. For Clip this is the only thing that clears it: a clip lamp that goes out on its own is a clip lamp you can miss by looking away.
  • Elapsed time is counted in samples, never in wall clock. A file analysed at 200× real time must produce exactly the same numbers as the same file played back live — that identity is how offline analysis is verified.
  • Every loudness window is built from 10 ms sub-blocks, so LUFS-M and LUFS-S advance every 10 ms and the Max of either resolves a transient to within 0.054 LU wherever it falls. The two gated windows still step 100 ms — the 75% overlap BS.1770 specifies for the 400 ms blocks behind LUFS-I, and the same rate for the 3 s blocks behind LRA — so the sub-block is finer than the standard’s grid without changing what the standard computes.

Conformance

CI runs the EBU Tech 3341 and 3342 cases on every push, on Linux, macOS and Windows, and fails the build if any result differs from the standard’s value by more than its stated tolerance. See packages/oaa_engine/test/conformance_test.dart.

The signals are generated rather than downloaded. Every case is a sine at a stated level or a sequence of them, so each is constructed exactly in a few lines — no fixtures, no network, no WAV decoder — and the expected values are derived from the standard in the comments rather than copied from somebody’s output. The suite also asserts two properties the standard does not state directly but which no correct implementation can violate:

  • Sample rate independence. The same tone reads the same loudness at 44.1, 48, 88.2, 96 and 192 kHz. This is what catches the tempting shortcut of using the 48 kHz coefficient table BS.1770-4 prints instead of designing the filter at the stream’s rate — a shortcut that passes every 48 kHz test there is and is wrong by a fraction of a dB on the most common delivery rate in music.

  • Block size independence. Pushing ten seconds in one call, in 512-frame device blocks, and in 377-frame chunks agree to within 0.001 LU.

  • Decoding does not change a reading. A generated signal analysed directly and the same signal written to a WAV, decoded and analysed again produce identical numbers, to the bit. That is the property offline analysis rests on, and it is asserted rather than assumed — see packages/oaa_engine/test/decode_test.dart.

The official vectors

Both official sets are run, and they are not a gate. The obstacle was never technical: neither body licenses its test material for redistribution here, and fetching 811 MB in CI would put a network dependency in front of the one suite that must never be flaky. So packages/oaa_engine/test/vectors_test.dart skips per group, unless told where an unzipped copy is:

cd packages/oaa_engine
OAA_VECTORS=~/ebu-loudness-test-set \
OAA_VECTORS_ITU=~/bs2217 \
  dart test test/vectors_test.dart
Set Where Cases
EBU Loudness Test Set v05 tech.ebu.ch 68. Table 1 of Tech 3341 entire — 1–8 integrated (both authentic programme segments included), 9–11 short-term, 12–14 momentary, 15–23 true peak — and Table 1 of Tech 3342, 1–6, for LRA.
Report ITU-R BS.2217 48 archives linked from the report 44. Twelve tones from 25 Hz to 10 kHz, the constant-loudness sweep, the absolute and relative gate tests, the 5.1 channel and summing checks, both LFE checks, 7.1, and ten programme files in mono, stereo and 5.1.

All 112 pass. Tolerances are the standards’ own: ±0.1 LU, +0.2/−0.4 dBTP, ±1 LU for LRA, ±0.1 LKFS for the ITU set.

Six ITU files are wider than 7.1 — 10, 12 and 24 channels — and the engine carries eight. Those are asserted to be refused: it has no weights for those layouts, and a number produced without them would be read as if it meant something.

The run was worth doing, because it found two defects the generated cases could not. Both are in CHANGELOG.md with their magnitudes:

  • Momentary loudness advanced only every 100 ms. Tech 3341’s tests 13 and 14 take a 400 ms tone — exactly one momentary window — and slide it through twenty files in 20 ms steps, so the tone lies inside exactly one window and no other. On a 100 ms grid sixteen of the twenty read up to 0.45 LU low, and test 14 up to 0.70. The sub-block is 10 ms now; both gating windows are still filed every 100 ms, so nothing integrating moved.
  • 7.1 carried the surround weight on its rear pair. The ITU’s channel table gives 7.1 as 1.00 / 1.00 / 1.00 / N/A / 1.41 / 1.41 / 1.00 / 1.00, and its two 7.1 files read 0.35 LU high until that was true. They now read −23.000 and −24.000 exactly.

Neither could have come from a suite that writes its own signals: one needs a tone that does not start at sample zero, the other needs a layout wider than the one the author was thinking about. That is the argument for material somebody else made — and equally the argument for not treating it as a replacement. The generated cases gate every push on three platforms and carry the sample-rate and block-size properties no shipped vector file asserts, so anything the official files caught that a generated signal can also express is asserted there too.


What a file report states

A snapshot mixes two kinds of quantity, and a report has to treat them differently or it describes the wrong thing.

Integrating — read once at the end, which is correct for them: LUFS-I, LRA and its percentiles, TP Max, Peak Max.

Instantaneous — these describe the moment they are read, so at the end of a file they describe the final block, which is usually the fade-out or silence. A report watches them across the whole programme instead:

Reported as Is
LUFS-M the highest momentary loudness reached
LUFS-S the highest short-term loudness reached
ODR-S the lowest short-term ratio reached, where it was defined — the most squeezed three seconds. odr_s_min in the JSON
Correlation the mean across the file; the panel also shows the range
Peak per channel the highest on each channel

ODR-I is derived — TP Max minus LUFS-I — rather than stored, so it cannot disagree with the numbers it is computed from. A target that sets a floor on it, or on the lowest ODR-S, adds a line to the verdict for each.

A file is analysed in blocks of the same size the realtime path uses. The gated loudness measurements are sample-accurate and genuinely independent of block size, but RMS, crest and the VU ballistics are computed per block, so pushing a whole file in one call would report one RMS averaged across the entire programme.