gcc_delay — ACOUSTICS dual op

• Data kinds: signal × signal → measurement

• Call: import fullseye as fs; fs.ledger.gcc_delay(a, b, rate=1.0, weight='phat', band=None, interpolate=True) (to call the implementation directly, import acoustics; acoustics.gcc_delay(a, b, rate=1.0, weight='phat', band=None, interpolate=True); from the registry, opsacoustics.get("gcc_delay"))

• Return value through the ledger: fullseye.ledger.gcc_delay(...) returns only the declared out type measurement (the underlying function also returns auxiliary values). When you need what was dropped, use fullseye.ledger.gcc_delay.raw(...) or call acoustics.gcc_delay directly.

Usage

Measures the time difference of arrival between 2 channels by generalized cross-correlation (GCC). → (delay, table).

Leak localization, sound-source direction, ultrasonic wall thickness, vibration propagation —— all are decided by the difference in "when the same source reached 2 places". This op returns that difference in seconds (in samples if rate is the default 1.0). To turn it into a position, multiply by path length and propagation speed (of the form x = (L - c·delay) / 2).

★The speed assumption becomes the position error as is. However clean the correlation, if the speed multiplied in is 10 % off, the position shifts in proportion to the distance from the path centre (measured in poc_leak_localization:

a leak 18 m from the centre gave +1.798 m, the geometric prediction is 1.800 m). Correlation quality and position correctness are separate quantities, so keep them apart in reports.

Args:

a, b: 1-D records of the same length. If b lags behind a, delay is positive

(b(t) ≈ a(t - delay)).

rate: sampling frequency [Hz]. With the default 1.0 the unit of the return is "samples".

weight: weighting of the cross-spectrum.

"none" = plain cross-correlation (best when SNR is high and there are no reflections),

"phat" = phase transform (whitens the amplitude; said to be robust to reverberation),

"roth" = 1/|A|², "scot" = 1/sqrt(|A|²|B|²).

★PHAT does not always win: on paths with asymmetric reflections the delay itself

is biased, so no weighting can remove it (measured: with reflection 0.8, raw 0.134 m /

PHAT 0.114 m, only 1 tenth apart, and the RMS is almost entirely bias).

band: narrows the band with (lo_hz, hi_hz) (same unit as rate; with rate=1.0,

0–0.5 in cycles / sample). None for the full band.

★Required with weight="phat" (the default) (2026-10-06, breaking change in 0.5.0).

PHAT whitens all bins to the same weight, so for a band-limited signal the bins without signal

(noise, leakage, rounding) enter the correlation with the same weight as the signal, and the peak misses

(for a low-frequency signal the hit rate drops sharply without band and recovers with it ——

the regression test in tests/test_acoustics.py). If you know the signal occupies the full band,

state it explicitly as band=(0.0, rate / 2). With "none" / "roth" /

"scot" it stays optional.

interpolate: reads to sub-sample precision by parabolic interpolation around the peak (default True).

If turned off, the quantization step remains as bias, not scatter (with the position fixed,

it misses in the same direction every time; the same as peak locking in PIV).

★Interpolation does not remove the bias: the correlation peak is sinc-like and a parabola

cannot approximate it fully. In measurements with white noise, full band and shifts of 0–1 samples,

the error is an S-curve of at most 0.117 samples (0 near integers, maximal around 0.3 / 0.7,

direction pulled toward the integer). Include this bias when talking about sub-sample accuracy.

Returns:

(delay, table): delay is a float in seconds (in samples if rate=1.0).

table is {"lags": lags of shape (2N-1,), "r": correlation values, "peak": peak value, "snr_peak": ratio of peak / secondary peak}.

★Via the ledger (fullseye.ledger.gcc_delay) only delay, the declared out type, is

returned. If you also need the correlation curve, use fullseye.ledger.gcc_delay.raw(...).

Raises:

ValueError: lengths differ / fewer than 2 / non-finite, weight unknown, band

not (lo, hi), lo >= hi or invalid for rate,

or band is None with weight="phat" (fail-closed).

Limits (honest): (1) the bias created by reflections, dispersion and path differences cannot be removed —— only the scatter due to noise can. (2) Since just 1 correlation peak is chosen, if a secondary peak wins under multipath it misses discontinuously (check snr_peak).

(3) Delays beyond half the record length wrap around.

Reference (public): C. H. Knapp, G. C. Carter, "The Generalized Correlation Method for Estimation of Time Delay", IEEE Trans. ASSP 24(4), 1976, 320-327.

Detailed usage guide

• acoustic_condition_monitoring family guide

References (sample data, literature)

• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).

• Operator provenance and references — the sources of the research/methods this op family came from.

• The canonical algorithm (author, year) and its uses are named in the family usage guide above.

Runnable examples (verified samples that actually call this op)

• acoustic_condition_monitoring — py -3.11 examples/acoustic_condition_monitoring.py

Ops the type connects to (they accept measurement as input)

—

Same category (dual)

coherence · transfer_function


*Provenance: acoustics.py — ACOUSTICS operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.