Introduction

There are generally two types of distortion that loudspeakers produce, time and spectrum distortion. Time and frequency distortions can be directly related to each other, but not always. The ToneBurst program focuses on Energy Decay. Here are some distortion examples:

Time Distortions

  • Phase
  • Delay
  • Energy Decay

Frequency Distortions

  • Frequency Response
  • Harmonic Distortion
  • Intermodulation Distortion

I initially learned about shaped tone burst testing from Sigfried Linkwitz's website 20+ years ago: https://www.linkwitzlab.com/mid_dist.htm

After studying up on burst testing I took it one step further, stepped sweep burst testing. Time analysis of speaker tone burst signals will reveal stored energy released after the input signal has stopped. This stored energy can be caused by the drivers, speaker cabinets, or room.

Here is a program I created to test tone bursts and stepped sweep tone bursts. You can read about some of its functions below, it will be expanded soon. If you decide to check it out, please remember that this program is not digitally signed, so your browser will throw a warning when you try to download it. To prevent the warning I would need to pay to get it digitally signed, I don't want to pay to get it signed. The program is free to use, there's no warranty or user agreement, use at your own discretion. If you decide to use it, all I ask is that you provide attribution back to this website. Suggestions are always welcome, use the contact email in the top menu.

DOWNLOAD - ToneBurst.exe


ToneBurst v2.3 — Reference Manual


📡

Overview

ToneBurst generates calibrated tone burst WAV files and analyzes their Energy-Time Curve (ETC) using the Hilbert Transform envelope method. It is designed to measure transient response, decay characteristics, and comparative differences between a Device Under Test (DUT) and a reference recording.


STEP 1
Generate

Create a burst or sweep WAV test signal

STEP 2
Record

Play through DUT, record the output

STEP 3
Analyze

Run analysis to produce ETC graphs

STEP 4
Compare

A/B two recordings to measure differences

STEP 5
View

Browse generated SVG / PNG graphs

Energy-Time Curve (ETC)

The ETC shows how energy decays over time after a tone burst. It is computed using the Hilbert Transform to extract the analytic signal envelope, displayed in dB. A clean transducer shows a sharp peak followed by rapid, smooth decay. Resonances appear as bumps or slow decay after the initial peak.

DUT vs Reference

The DUT (Device Under Test) is the recording through the device being measured. The reference is a direct or known-good recording of the same signal. Overlaying them reveals differences in transient behavior, energy storage, and decay rate.

|Diff| % Metric

The primary comparison metric is |Diff| % — the absolute area difference between the DUT and reference ETC curves, expressed as a percentage of the reference area above the threshold. Lower is better; 0% means the DUT is identical to the reference above the analysis threshold.


Generate

Creates calibrated WAV test signals. Two modes are available: Single Burst generates one tone at a fixed frequency; Sweep generates a series of bursts stepping through a frequency range at a defined octave resolution. Output files are written to the GEN directory.


Single Burst

Generates a single sinusoidal tone burst at the specified frequency. The burst is a short, windowed sine wave at peak amplitude, followed by silence. DTMF markers are embedded before and after the burst so the analyzer can automatically locate it. Output: WAV and optionally SVG PNG graphs.

Sweep

Generates a sequence of tone bursts stepping from Start Hz to End Hz in 1/N octave steps. Each burst is separated by a silence gap and uniquely identified by DTMF encoding. Designed to be played once through the DUT while recording the output, capturing all test frequencies in a single take.

ParameterModeDescriptionDefault
Frequency (Hz)BurstThe centre frequency of the tone burst in Hz. Valid range: 1 Hz – 47 999 Hz.1000
Start (Hz)SweepLowest frequency in the sweep sequence.100
End (Hz)SweepHighest frequency in the sweep sequence.20000
1/N OctSweepFrequency resolution. 3 = 1/3 octave steps, 6 = 1/6 octave, etc. Higher values produce more test frequencies.3
Headroom (dB)BothPeak level below full scale (0 dBFS). 3 dB headroom means the burst peaks at −3 dBFS.3
Noise (dB below)BothAdds Gaussian pink noise at the specified level below the burst peak. Used to simulate real recording conditions or test SNR performance.off
WAVBurstOutput a WAV file of the generated signal to the GEN directory.on
SVG / PNGBurstImmediately analyze the generated WAV and produce ETC graph output files.off
DistortionBothApplies a multi-mode peaking EQ to simulate resonant distortion. Each of 6 modes has independent frequency ratio, Q, gain, window cycles, and delay settings. Enable the checkbox to expand the mode editor.off

📊

Analyze

Analyzes a DUT recording against its embedded reference signal. The analyzer auto-detects whether the WAV is a single burst or a sweep using the embedded DTMF markers, then dispatches to the appropriate analysis engine. Output files are written to the IMG directory.


Auto-Detection

The first DTMF digit embedded in the WAV file identifies the recording type. Digit 1 = single burst; digit 2 = sweep. The analyzer reads this automatically — no manual mode selection is required.

Burst Output

Produces an ETC (Energy vs. Time Curve) graph showing the DUT envelope in magenta and the reference envelope in blue on the same axes. Outputs: SVG PNG

Sweep Output — SVG Sweep

A single frequency-vs-|Diff|% chart covering the full sweep range on a log frequency axis. Shows how the DUT differs from reference at every tested frequency. Y axis range is configurable (default 0–20%).

Sweep Output — SVG Mini

A grid of small ETC thumbnails, one per test frequency, showing the DUT (magenta) and reference (blue) curves side by side. Useful for quickly spotting which frequencies have abnormal decay.

Sweep Output — SVG Discrete

Individual full-size ETC graphs for each frequency in the sweep, saved as separate files. Equivalent to running burst analysis on every frequency individually.

ParameterDescriptionDefault
WAV FilePath to the DUT recording. Can be in the DUT directory (filename only) or a full path. Use Browse to navigate.
Threshold (dB)Analysis threshold in dB below peak. Only signal above this level is included in the area integral. Increase to reduce noise influence; decrease to include more of the tail.40
Window CycAnalysis window size in periods of the burst frequency. Wider windows capture more of the decay tail; narrower windows focus on the main burst.16
No Burst OverlayRender the ETC graph without the reference overlay curve. Useful when analyzing a recording that has no reference (e.g., a single-channel capture).off
Noise FloorMeasure and display the noise floor of the recording as a horizontal line on the ETC graph.off
Set Noise FloorUse the measured noise floor as the analysis threshold, overriding the manual Threshold value. Ensures the integral stops at the actual noise level.off
ETC MarkersOverlay peak and −3 dB crossing markers on ETC graphs. Shows the burst peak as a vertical dashed line and the −3 dB half-power points for both DUT and reference.off
SVG Sweep Y Min / Max %Sets a fixed Y axis range for the SVG Sweep frequency chart. Leave blank for automatic scaling. The default 0–20% range suits most measurements; increase for highly distorted devices.0 / 20

⚖️

Compare A/B

Compares two DUT recordings of the same test signal against each other, or against a shared reference. Produces an overlay ETC graph with crosshatch difference shading and quantitative |Diff|% statistics for each recording.


SVG Overlay

Renders DUT A (magenta) and DUT B (blue) on the same ETC axes, with the shared reference in green dashed. Yellow crosshatch highlights where A exceeds reference; blue crosshatch highlights where B exceeds reference. |Diff| % values for both are printed in the graph subtitle.

CSV Export

Exports per-sample ETC data for both recordings to a CSV file for post-processing in spreadsheet software or other analysis tools.

ParameterDescriptionDefault
File AFirst DUT recording WAV file. Must be a burst recording containing an embedded reference signal.
File BSecond DUT recording WAV file for comparison. Must be from the same test signal as File A.
Label A / BShort labels used to identify each recording in the graph legend and CSV header.A / B
Threshold (dB)Analysis threshold below peak. Identical to the Analyze tab threshold — defines the integration region.40
Window CycAnalysis window size in periods. Should match the setting used when analyzing individually.16
SVG OverlayGenerate the A/B comparison SVG graph with both curves and difference shading.on
CSV ExportExport per-sample ETC values for both recordings to a CSV file.off

🖼

View

Built-in image browser for SVG and PNG output files. Displays graphs directly in the application window without needing an external viewer. Auto-fits images to window width and supports keyboard navigation through a directory of files.


Select Directory

Choose a folder to browse. All SVG and PNG files in the directory are loaded into the navigation list. The IMG directory is used by default. Files are sorted alphabetically.

Browse File

Open a specific SVG or PNG file directly. The file's parent directory is automatically loaded for navigation, so you can Page Up / Page Down through neighbouring files after selecting one.

Page Up / Page Down

Cycle through all images in the current directory. Works both via the ◀ PgUp / PgDn ▶ buttons and the keyboard Page Up / Page Down keys when the View tab is active.

Zoom Controls

+ zooms in, zooms out in 25% increments. Fit restores auto-fit-to-width mode, which also re-applies automatically whenever the window is resized while in fit mode.


📁

Directories

ToneBurst organizes files into three sub-directories relative to the application executable. They are created automatically on first run.


GEN — Generated Signals

WAV files produced by the Generate tab are saved here. Files are named toneburst_<freq>Hz.wav for bursts and toneburst_sweep_<start>-<end>Hz_1-<N>oct.wav for sweeps.

DUT — Device Under Test

Place your recorded WAV files here. The Analyze and Compare tabs default their browse dialogs to this directory. Files can be referenced by filename alone if placed here.

IMG — Image Output

All SVG and PNG graphs produced by analysis are saved here. The View tab defaults to browsing this directory. Filenames include the source WAV name and graph type (e.g. _sweep.svg, _mini1.svg, _100Hz.svg).

HELP — Documentation

This help file (tonebursthelp.html) is saved here and can be reopened at any time from the Help button on the Generate, Analyze, or Compare tabs.


💻

Command Line Interface

ToneBurst can be run from the command line for automation and scripting. Run without arguments to launch the GUI, pass a command flag to run headlessly.


# Generate a single burst at 1 kHz
ToneBurst -genburst 1000 -wav

# Generate a sweep from 100 Hz to 20 kHz at 1/3 octave
ToneBurst -gensweep -sweepstart 100 -sweepend 20000 -sweepoct 3

# Analyze a recording (auto-detects burst or sweep)
ToneBurst -analyze DUT\my_recording.wav

# Analyze burst with SVG + ETC markers
ToneBurst -analyze DUT\burst.wav -svg -etcmarkers

# Analyze sweep, all output formats, fixed Y axis 0–10%
ToneBurst -analyze DUT\sweep.wav -svgsweep -svgmini -svgdiscrete -sweepymin 0 -sweepymax 10

# Generate with noise and distortion
ToneBurst -genburst 1000 -wav -headroom 3 -noise 60
Switch/FlagApplies ToDescription
-genburst <Hz>GenerateGenerate a single tone burst at the given frequency.
-gensweepGenerateGenerate a sweep sequence (requires -sweepstart, -sweepend, -sweepoct).
-wavGenerateOutput a WAV file.
-analyze <file>AnalyzeAnalyze a sweep or burst recording.
-threshold <dB>AnalyzeAnalysis threshold below peak (default: 40).
-window <cyc>AnalyzeWindow size in periods (default: 16, minimum: 4).
-noisefloorAnalyzeMeasure and show noise floor on graphs.
-setnoisefloorAnalyzeUse measured noise floor as analysis threshold.
-etcmarkersAnalyzeShow peak and −3 dB markers on ETC graphs.
-headroom <dB>BothPeak headroom below 0 dBFS (default: 3).
-noise <dB>BothAdd Gaussian pink noise at dB below peak.
-svg / -pngBurstOutput SVG / PNG graph for burst analysis.
-svgsweep / -pngsweepSweepOutput SVG / PNG frequency sweep chart.
-svgmini / -pngminiSweepOutput SVG / PNG mini ETC grid.
-svgdiscrete / -pngdiscreteSweepOutput individual SVG / PNG ETC graphs per frequency.
-sweepstart <Hz>SweepFirst frequency in sweep sequence.
-sweepend <Hz>SweepLast frequency in sweep sequence.
-sweepoct <N>Sweep1/N octave step resolution.
-sweepymin <%>SweepFixed Y axis minimum for sweep chart (default: auto).
-sweepymax <%>SweepFixed Y axis maximum for sweep chart (default: auto).

WAV Output File Structures

Single Burst & Burst Sweep signal format specification

24-bit 96 kHz Mono −3 dB default headroom

Single Burst WAV

A single 4-cycle Blackman-windowed tone burst at one target frequency, framed by DTMF-encoded metadata and band-limited PRN sync markers.

Silence1000ms
DTMF6 digits
Silence1000ms
PRN100ms
Silence1000ms
Burst4 cyc
Silence1000ms
Noise Floor1000ms
PRN100ms
Silence500ms
Silence
DTMF
PRN Sync
Tone Burst
Noise Floor
#RegionDurationDescription
1Silence1000 msLead-in silence
2DTMF Encoding6 × 75 msType-prefixed frequency: 1FFFFF — digit 1 identifies burst type, followed by 5-digit zero-padded frequency (e.g. 101000 for 1000 Hz). Each digit is a 50 ms dual-tone + 25 ms gap at 25% peak amplitude, Hann-windowed. Band selected automatically by test frequency.
3Silence1000 msGap after DTMF
4Start PRN Sync100 msBand-limited PRN — sum of sinusoids at 1/12-octave spacing from 100 Hz to 20 kHz, with 1/√f pink weighting and deterministic LCG phases. High-pass filtered via 2-pole Butterworth at freq/2 (capped 2 kHz). 50% peak amplitude, 10 ms Hann fade in/out.
5Silence1000 msGap after PRN
6Tone Burst4 cycles4-cycle Blackman-windowed sine burst at the target frequency, plus optional distortion tail from multi-mode peaking EQ.
7Silence1000 msGap before noise floor region
8Noise Floor1000 msSilent region used for noise floor measurement
9End PRN Sync100 msSame band-limited PRN signal as start, with Hann fade in/out
10Silence500 msTrail-out silence
Optional overlays: Multi-mode peaking EQ distortion on the burst region, and pink noise across the entire signal.

Burst Sweep WAV

Multiple 4-cycle bursts at logarithmic spaced frequencies, sharing the same DTMF-first framing structure as the single burst.

Silence1000ms
DTMF17 digits
Silence1000ms
PRN100ms
Silence1000ms
Burst RegionN × interval
Silence1000ms
Noise Floor1000ms
PRN100ms
Silence500ms
Silence
DTMF
PRN Sync
Burst Region
Noise Floor
#RegionDurationDescription
1Silence1000 msLead-in silence
2DTMF Encoding17 × 75 msType-prefixed sweep parameters: 2SSSSSEEEEEOOIIII — digit 2 identifies sweep type, followed by 5-digit start freq, 5-digit end freq, 2-digit octave division, 4-digit interval (ms). Band selected by sweep start frequency.
3Silence1000 msGap after DTMF
4Start PRN Sync100 msBand-limited PRN — HP filtered via 2-pole Butterworth at startFreq/2 (capped 2 kHz). 50% peak amplitude, 10 ms Hann fade in/out.
5Silence1000 msGap after PRN
6Burst Regioninterval × countRepeating fixed-length slots. Interval = 25× the period of the lowest frequency, minimum 250 ms. Each slot has 500 silent samples then the burst. Frequencies step by 21/OctDiv from start to end.
7Silence1000 msGap before noise floor region
8Noise Floor1000 msSilent region used for noise floor measurement
9End PRN Sync100 msSame band-limited PRN signal as start, with Hann fade in/out
10Silence500 msTrail-out silence

Key Differences from Single Burst

  • DTMF type prefix 2 (sweep) vs 1 (burst) — auto-detected by analyzer
  • DTMF payload encodes sweep parameters (17 digits) instead of a single frequency (6 digits)
  • PRN is band-limited to the sweep start frequency range
  • Burst region contains many fixed-interval slots instead of one burst

DTMF Type Prefix

The first DTMF digit identifies the file type, allowing the analyzer to auto-detect and route to the correct analysis path.

PrefixTypeFormatTotal Digits
1 Single Burst 1FFFFF 6
2 Burst Sweep 2SSSSSEEEEEOOIIII 17

DTMF Band Selection

The DTMF band is chosen automatically to avoid overlap with the test frequency. Each digit is encoded as a simultaneous pair of tones — one from the Low Group (row) and one from the High Group (column).

LOW Band
Test freq ≤ 800 Hz
Low Group (rows)
697 Hz 770 Hz 852 Hz 941 Hz
High Group (cols)
1209 Hz 1336 Hz 1477 Hz 1633 Hz
MID Band
801 – 4000 Hz
Low Group (rows)
2800 Hz 3080 Hz 3400 Hz 3760 Hz
High Group (cols)
4840 Hz 5340 Hz 5900 Hz 6530 Hz
HIGH Band
Test freq > 4000 Hz
Low Group (rows)
7900 Hz 8700 Hz 9600 Hz 10600 Hz
High Group (cols)
13700 Hz 15100 Hz 16700 Hz 18500 Hz

Digit → Row / Column Mapping

Each digit 0–9 selects one frequency from the Low Group (row index) and one from the High Group (column index). The two tones are transmitted simultaneously for 50 ms.

DigitRow IndexCol IndexExample (MID Band)
0313760 Hz + 5340 Hz
1002800 Hz + 4840 Hz
2012800 Hz + 5340 Hz
3022800 Hz + 5900 Hz
4103080 Hz + 4840 Hz
5113080 Hz + 5340 Hz
6123080 Hz + 5900 Hz
7203400 Hz + 4840 Hz
8213400 Hz + 5340 Hz
9223400 Hz + 5900 Hz

PRN Sync Signal

The sync signal is a sum-of-sinusoids — a deterministic, reproducible waveform constructed by adding together a large number of sine waves simultaneously. Here's each stage in detail.

Sweep Generation (-gensweep)

  • Frequency grid — 1/12-octave spacing starting at 100 Hz, each successive frequency is multiplied by 2^(1/12) ≈ 1.0595, the same interval as a semitone in musical pitch. This continues up to 20 kHz, producing approximately 96 frequencies covering the full audio range. Using logarithmic spacing means the frequencies are perceptually evenly spread — as many components cover 100–200 Hz as cover 10–20 kHz — which gives the signal a noise-like texture across the whole band rather than clustering energy at the low end.
  • The sum-of-sinusoids controls exactly which frequencies are present and at what amplitude, you can shape the spectrum to match the measurement context and guarantee that the generator and detector always use bit-for-bit identical reference waveforms regardless of platform or runtime. The cross-correlation between the recorded signal and the known reference then has a sharp, unambiguous peak at the correct sync position even if the recording is band limited or frequency colored by the device under test.
  • Phase randomisation — All those sine waves starting at zero phase would produce a huge coherent spike at t=0. To prevent that, each sinusoid is given a pseudo-random starting phase. The phases are generated by the classic glibc Linear Congruential Generator. The output of each step is mapped to a phase in the range 0–2π. All that's needed is that the phases are sufficiently spread out to break the coherent spike, and that the exact same phases are reproduced every time the code runs, so the generator and detector always agree on the reference waveform.
  • Pink Noise amplitude weighting 1/√f — Each sinusoid is scaled by √(refFreq / f), where refFreq is the lowest frequency (100 Hz). This means the 100 Hz component has full amplitude (scale = 1.0), the 200 Hz component has scale ≈ 0.707, the 1 kHz component has scale ≈ 0.316, and the 20 kHz component has scale ≈ 0.071. This is a pink weighting — amplitude falls at 3 dB per octave, which makes the power spectrum flat on a per-octave basis. Without this, the higher frequencies would dominate (white noise) the signal energy and cross-correlation would be biased toward low-frequency content in the recording.
  • High-pass filtering - The full-bandwidth signal is then filtered with a 2nd-order Butterworth high-pass at half the lowest burst frequency (capped at 2 kHz). This ensures the PRN doesn't overload a driver, especially small mids and tweeters. For a 1 kHz burst the PRN is high-passed at 500 Hz; for a 100 Hz sweep start it would be high-passed at 50 Hz but the 2 kHz cap applies in practice for any higher frequency tests

DUT Analysis (-analyze)

  • The analysis pipeline has six distinct step that apply identically whether processing a single burst or a sweep. The sweep simply iterates steps 4–6 once per frequency.

  • Step 1 Reading the WAV File — The WAV is read into memory and scanned in 10 ms energy windows. The first window that exceeds 10× the RMS noise floor (or 50,000 counts absolute minimum) is flagged as the DTMF start. A Goertzel filter then reads just the first DTMF digit across all three frequency bands (LOW/MID/HIGH) simultaneously and picks the band with highest total power. Digit 1 → burst and Digit 2 → sweep. This determines which analysis path runs next.
  • Step 2 DTMF Parameter Decoding — The full digit string is decoded using the Goertzel algorithm at the known symbol timing (50 ms tone, 25 ms gap per digit). Every possible band is tried and the one producing the highest total energy across all digits wins. Burst (1FFFFF): 6 digits → frequency extracted as a 5-digit integer. If this fails, FFT is used as fallback. Sweep (2SSSSSEEEEEOOIIII): 17 digits → start frequency, end frequency, octave resolution, and burst interval in ms are all extracted. These values completely describe the test — no external parameters are needed.

  • Step 3 PRN Sync and Clock Drift Correction — A reference PRN signal is generated in software using the same function as the generate tab. This is cross-correlated against the recording to locate the start PRN precisely. Two-pass correlation: First pass steps every 100 samples across a ±200 ms search window around the expected position for speed. Second pass does a sample-by-sample refinement ±10 samples around the coarse peak. The sub-sample position is resolved by fitting a parabola to the three highest correlation values — sub-sample function returns a fractional sample offset so the PRN is located to better than one sample precision. The End PRN is then found by the same process, searching the second half of the file. With both PRN positions known sub-sampled precisely:
  • measuredSpan = endPRN_precise − startPRN_precise
  • expectedSpan = known from DTMF (PRN + silence + bursts + silence + noise floor)
  • driftRatio = measuredSpan / expectedSpan
  • driftPPM = (driftRatio − 1) × 1,000,000
  • If drift exceeds 0.5 PPM the entire recording is resampled by driftRatio using windowed sinc interpolation (DSPHelper.Resample), and all sample offsets are recalculated. If drift exceeds 1000 PPM (implausible — different clocks or wrong file) it is discarded. This makes burst timing precise even when the playback and recording devices have independent clocks.
  • Step 4 Noise Floor Measurement — If requested, the 1-second silence window immediately before the end PRN is used. The peak absolute sample value in that window is expressed relative to 0 dBFS — this is the noise floor in dBFS. For each individual burst analysis it is then expressed relative to the burst's own peak, giving a burst-relative noise floor in dB. If -setnoisefloor is active, this value replaces the manually set threshold for area integration.
  • Step 5 Per Burst Extraction and ETC Computation — For each burst slot (sweep: once per frequency; single burst: once.) The interval window is sliced from the drift-corrected recording and the burst is extracted. The first 500 samples (Burst Lead-In) are silent pre-burst padding, deliberately included because the Hilbert transform needs silence before the burst onset to avoid edge effects. Window length is 500 + WindowPeriods × samplesPerCycle — defaulting to 16 periods, extended to ensure the Windowed/Discrete Hilbert Transform (DHT) has full support at every sample.
  • Peak location: A frequency-adaptive RMS window, 4-cycle width, is slid across the interval to find the burst peak position. Silent intervals (below 0.1% of full scale) are skipped.
  • Reference generation: A mathematically perfect 4-cycle Blackman-windowed burst at the nominal frequency is synthesized and placed at sample offset 500 within an array of the same length as the DUT window. This is the ideal reference — no room acoustics, no recording chain, just the pure waveform.
  • Discrete Hilbert Transform envelope: Both DUT and reference windows are passed to the envelope. The DHT is a windowed FIR approximation of the ideal 2/(πk) impulse response, Blackman-windowed to suppress side lobes, with a radius of at least 8 periods of the burst frequency. The input is zero-padded by half-width on both sides so the convolution is accurate at all positions. At each sample, the imaginary part (Hilbert output) and real part (original signal minus DC) form a complex pair; the magnitude is √(real² + imag²). This gives the instantaneous amplitude envelope. The result is converted to dB relative to peak and clamped to a −60 dB floor.
  • Step 6 |Diff| % Computation — Both envelopes are converted back to linear amplitude for integration. For each consecutive sample pair where at least one envelope is above the threshold, the absolute difference is computed and the area under it is integrated using the trapezoidal rule.
  • diffArea += 0.5 × (|DUT[i] − REF[i]| + |DUT[i+1] − REF[i+1]|) × dt
  • The DUT area alone is computed the same way (against zero). The |Diff| % metric is: |Diff| % = (diffArea / refArea) × 100
  • This expresses how much the DUT's energy-time behavior deviates from the ideal reference, as a fraction of the reference's own energy above the threshold. A perfect transducer scores 0 %. A device with strong resonant ringing scores higher — there is no upper bound to how badly a device can behave, but the value is capped at 200 % in the code to prevent chart scaling problems.

Sweep Burst Interval

Each burst in the sweep occupies a fixed-length interval. The first 500 samples are guaranteed silent, providing a clean pre-burst padding zone for the Hilbert kernel in the analyzer.

interval = max(250 ms, 25 × period of lowest frequency)

Example: for a 100 Hz–20 kHz sweep, interval = max(250, 25 / 100 × 1000) = 250 ms = 24,000 samples at 96 kHz.

500 silent 4-cycle burst remaining silence (decay / tail space) interval (24,000 samples @ 100 Hz start) sample 500 0 24,000
Burst interval structure — 500-sample silent lead-in guarantees Hilbert padding

Analysis Windowing

Both burst and sweep analyzers extract a time-domain window around each burst for ETC (Energy Time Curve) analysis via Hilbert transform. The window must include enough silent padding before the burst for the Hilbert kernel to operate without edge truncation.

Single Burst Window

The single burst analyzer locates the burst via PRN sync correlation, then extracts a window centered on the burst peak. The window size is based on the number of analysis periods (default 16) plus extra room for filter delay and ringing tail.

...silence... burst ...silence... Hilbert padding tail / ringing space windowSize = max(2048, 16 periods + 2 × burstLen)
Single burst — window centered on burst peak, symmetric padding

Sweep Burst Window

The sweep analyzer extracts each burst's fixed-length interval starting from the interval boundary. The 500-sample silent lead-in provides guaranteed Hilbert padding regardless of frequency. The window starts at sample 0 of the interval.

interval N−1 interval N (selected) interval N+1 500 tail / decay space ref burst window = max(2048, 16 periods + 2 × burstLen) sample 500 →
Sweep burst — window starts at interval boundary, 500-sample guaranteed lead-in. Reference burst placed at identical position (sample 500) for consistent alignment.
Hilbert kernel size: M = max(255, samplesPerPeriod × 8). At 16 kHz / 96 kHz SR, M = 255 and minPadding = 265. The 500-sample lead-in exceeds this at all frequencies.

ETC Analysis & Oversampling

The ETC (Energy Time Curve) is computed via Hilbert transform at the native 96 kHz sample rate for maximum waveform fidelity. The resulting dB envelope is then oversampled to 768 kHz (8×) for sub-sample alignment precision and smooth SVG rendering.

Processing Pipeline

Input
int[] samples
96 kHz native
Hilbert Transform
ComputeEnvelope()
96 kHz, kernel M
Output
dB envelope
96 kHz native
Oversample 8×
OversampleEnvelope()
768 kHz
Align
left −3 dB edge
sub-sample shift
Diff Area
|DUT − REF|
768 kHz precision

Why Oversample the Envelope, Not the Waveform?

The Hilbert transform produces the smoothest, most accurate envelope when operating on the original integer samples at the native sample rate. Upsampling the waveform before the Hilbert introduces sinc interpolation artifacts (ripple near transitions) that the kernel picks up as spurious envelope features. By contrast, the dB envelope is a smooth, slowly-varying curve that oversamples cleanly with simple interpolation.

StageSample RatePurpose
Hilbert transform96 kHzAnalytic signal envelope from original waveform — no interpolation artifacts
Envelope oversample768 kHz (8×)Sub-sample precision for −3 dB alignment and area integration
Fractional shift768 kHzWindowed sinc interpolation aligns DUT left −3 dB crossing to REF
|Diff| area768 kHzTrapezoidal integration of |DUT − REF| above threshold, reported as ms² and %

Alignment Method

DUT and REF envelopes are aligned by their left (rising) −3 dB crossing point. This edge is unaffected by tail ringing or distortion, giving a clean onset alignment. The shift is computed at 768 kHz resolution (1.3 µs precision) and applied via windowed sinc interpolation on the oversampled envelope.

0 dB −3 dB −40 dB −60 dB threshold REF DUT (with ringing tail) align here (left −3 dB) |Diff| area Time (ms)
ETC envelope alignment — left −3 dB crossing used for onset registration. Difference area (gold) computed above threshold between DUT and REF.

ETC Output Layout

Etc Output Layout
Grid layout of per-frequency ETC mini-graphs with |Diff| % values

Tone Burst Bandwidth

The bandwidth of a tone burst is determined by its duration, not its frequency. For a 4-cycle burst the duration is T = 4 / f and the approximate −3 dB bandwidth is BW ≈ f / 4 — roughly 25% of the center frequency (±12.5%).

The Blackman window reduces spectral leakage (sidelobes ≈ −58 dB down) but slightly widens the main lobe, so the actual −3 dB bandwidth is closer to f / 3.5 or about 29% of center frequency.

FrequencyDurationBandwidth (−3 dB)
100 Hz40 ms~25 Hz
1 kHz4 ms~250 Hz
10 kHz0.4 ms~2.5 kHz
20 kHz0.2 ms~5 kHz

This is why tone bursts are useful for transient / time-domain analysis — they are short enough to measure time-domain behavior but have enough bandwidth to excite the system meaningfully. The trade-off is that you cannot isolate a single frequency the way you would with a long steady-state sine wave.

For speaker measurements, this bandwidth is actually desirable since it shows how the speaker responds to transient signals across a range of frequencies simultaneously, which is more representative of real audio content (music, speech) than pure tones.

4-Cycle Blackman-Windowed Reference Burst

Blackman Tone Burst
4-cycle Blackman-windowed tone burst showing amplitude modulation envelope (dashed orange)

Optimal Octave Spacing

For adjacent burst spectra to "just touch" at their −3 dB points, we need the upper −3 dB edge of one burst to meet the lower −3 dB edge of the next.

Given

Bandwidth ≈ 29% of center frequency (±14.5%). Upper −3 dB edge: f × 1.145. Lower −3 dB edge: f × 0.855.

Derivation

f₂ × 0.855 = f₁ × 1.145
f₂ / f₁ = 1.145 / 0.855 = 1.339

21/n = 1.339 → 1/n = log₂(1.339) = 0.421 → n ≈ 2.37
SettingStep RatioCoverage
-sweepoct 2 (½ octave)1.414Slight gaps between bursts
Optimal ≈ 1/2.4 octave1.339Spectra just touch
-sweepoct 3 (⅓ octave)1.260Slight overlap (~6%)

Since -sweepoct takes integers, use -sweepoct 3 or higher for continuous frequency coverage without gaps.

Parabolic Interpolation for Sub-Sample PRN Detection

Test Signal Structure

Test Signal Structure
WAV file structure showing Start PRN and End PRN positions used for drift measurement

The Problem: Integer Sample Resolution

Cross-correlation finds where the PRN best matches, but only at integer sample positions. The true peak of the correlation function almost always falls between samples. A 1-sample error in a 770,400-sample span produces a 1.3 PPM apparent drift.

Cross Correlation Peak
Cross-correlation values at integer sample positions; the true peak lies between samples

The Solution: Fit a Parabola

A parabola closely approximates the correlation peak. We use the three samples surrounding the integer maximum — y0, y1 (the peak), and y2 — to calculate where the true peak lies.

Parabolic Interpolation
Parabola fitted through three consecutive correlation values to find the sub-sample peak

The Math

For a parabola passing through points at x = −1, 0, +1 the vertex (peak) occurs at:

δ = (y0 − y2) / (2 × (y0 − 2·y1 + y2))

Real Example (End PRN Detection)

y0 (lag−1) :  527,410,999
y1 (lag peak): 529,429,464   ← highest correlation
y2 (lag+1) :  527,361,859
y0 − y2          = 49,140
y0 − 2·y1 + y2  = −4,086,070
δ = 49,140 / (2 × −4,086,070) = −0.006013
Integer position  : 866,400
Sub-sample offset : −0.006013
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Precise position  : 866,399.993987
              
Sub Sample Result
Correlation values at three consecutive sample positions around the End PRN peak

Precision Improvement

Without Interpolation

Start PRN: 96000
End PRN: 866400
Span: 770,400 samples
Error: ~1 sample
Drift: ~1.3 PPM

With Parabolic Interpolation

Start PRN: 96000.00513
End PRN: 866399.993987
Span: 770,399.988857
Error: 0.011 samples
Drift: ~0.014 PPM

Detection MethodResolutionMin Detectable Drift
Integer only1 sample~1.3 PPM
Parabolic interpolation~0.01 sample~0.013 PPM
~90× Better Precision

Typical consumer audio drift is 20–100+ PPM; professional gear is 1–20 PPM. With parabolic interpolation we can accurately measure even professional-grade clock accuracy.

|Diff| % Metric

The |Diff| % metric compares the Energy Time Curve (ETC) of the Device Under Test (DUT) to an ideal 4-cycle Blackman-windowed reference burst. It measures how much the burst "spreads" or "rings" compared to the ideal.

Step 1 — Record the Signals

The reference is the ideal 4-cycle Blackman burst. The DUT signal is recorded through the speaker and room, and may show additional ringing after the main burst.

Ref Vs Dut Waveform
Reference signal (top) vs. DUT signal (bottom) showing post-burst ringing

Step 2 — Compute ETC (Envelope via Hilbert Transform)

The Hilbert Transform extracts the amplitude envelope, which is then converted to dB scale (0 dB = peak).

Etc Envelopes
ETC envelopes in dB scale; the −40 dB threshold (orange dashed) defines the integration boundary

Step 3 — Calculate Area Above −40 dB Threshold

We integrate the linear envelope (not dB) above the −40 dB threshold. The shaded regions below represent the areas being compared.

Area Above Threshold
Shaded areas above the −40 dB threshold for Reference (top) and DUT (bottom)

Step 4 — Calculate |Diff| %

|Diff| % = |DUT Area − Reference Area| / Reference Area × 100%

= |19.5 − 17.0| / 17.0 × 100% = 2.5 / 17.0 × 100% = 14.7%

Visual Summary

Diff Percent Visual
Side-by-side comparison: ideal burst vs. burst with ringing tail

Interpretation Guide

|Diff| %RatingInterpretation
0–5%ExcellentMinimal ringing or resonance
5–15%GoodSome coloration
15–30%FairNoticeable resonance
30–50%PoorSignificant ringing
>50%BadSevere resonance issues
What the Metric Captures

Speaker resonance (cone continues moving after signal stops), room reflections (sound bouncing back to microphone), cabinet vibrations (enclosure ringing), and port turbulence (in ported speakers).

Noise Floor Measurement

The noise floor is measured from a dedicated 500 ms silence window located just before the End PRN marker.

Measurement Window Location

Noise Measurement Window
The 500 ms noise measurement window is located between the last silence gap and the End PRN

Step 1 — Locate the Window

noiseFloorSilence    = SampleRate × 0.500    # 48,000 samples at 96 kHz
noiseFloorEndSample  = endPrnPosition
noiseFloorStartSample = endPrnPosition − noiseFloorSilence
              

Step 2 — Calculate RMS

RMS (Root Mean Square) measures the average power of the signal in the noise window.

RMS = √( (s₀² + s₁² + s₂² + … + sₙ²) / N )
Noise Samples
Visualisation of noise samples in the measurement window (exaggerated amplitude)

Step 3 — Convert to dBFS

Convert the RMS value to decibels relative to full scale (maximum possible digital value).

dBFS = 20 × log₁₀( RMS / Full Scale Max )

For 24-bit audio: Full Scale Max = 8,388,607 (2²³ − 1)
Example:  RMS = 3,340
dBFS = 20 × log₁₀( 3,340 / 8,388,607 )
     = 20 × log₁₀( 0.000398 )
     = 20 × (−3.4)
     = −68 dBFS
              

Step 4 — Per-Burst Relative Noise Floor

For each burst's mini ETC graph, the noise floor is calculated relative to that burst's peak amplitude, giving the signal-to-noise ratio for that specific frequency.

Per Burst Noise Floor
Per-burst ETC graph with the noise floor shown as an orange dashed line relative to the burst peak
Relative Noise Floor = 20 × log₁₀( Noise RMS / Burst Peak Amplitude )

Example: 20 × log₁₀( 3,340 / 6,700,000 ) = 20 × log₁₀( 0.000499 ) = −66 dB

Two Different Noise Floor Values

Absolute (Console Output)

"Noise Floor: −58.1 dBFS (measured from silence window)"

Measured relative to full scale (0 dBFS). Same value for the entire file. Tells you the actual noise level.

Relative (Per-Burst Graph)

Orange dashed line at −XX dB on each mini ETC graph.

Measured relative to each burst's peak amplitude. Different per burst (lower freq = higher amplitude). Shows SNR for that burst.

Why Measure in the Silence Window?

Captures system noise without signal interference. Located after all bursts so no burst energy leaks in. 500 ms provides enough samples for a stable RMS measurement. Positioned before the End PRN so the PRN doesn't corrupt the measurement.

Noise sources captured: ADC quantization noise, preamp/mic noise, environmental noise (room, HVAC, etc.), and electromagnetic interference.