Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity
Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity
Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity
Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity
Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity
Core metrology guides: result figures, ResampledSignalResult.plot() and real introductions (#364)
* Add ResampledSignalResult.plot(): the delivered anti-alias filter against its design spec
* Rewrite the multichannel guide intro: concrete use cases, per-channel guarantees, Bendat & Piersol citations
* Give the levels page a real introduction: descriptor families, when-to-use guidance and survey references
* Time weighting: framing intro with detector history, ANSI S1.4/Bies references and sibling links
* Calibration: proper introduction (SPL vs dBFS choice, workflow framing) with Bies reference and sibling links
* Add eleven core-metrology figures: resampling spec, cepstrum variants, liftering, correlation, IR alignment, Hilbert envelope, cross-spectra, Golay recovery, TSA noise law, runs test
* Test signals: anti-alias figure with dual snippet, res.plot() mention, See also, docs mirror sync
* Cepstrum guide: variants and liftering figures with dual snippets, complex-cepstrum plot mention
* Correlation guide: normalization, IR-alignment and Hilbert-envelope figures with dual snippets
* Spectral analysis: cross-spectral density and coherent-output-SNR figures with dual snippets
* System measurement: Golay exact-recovery figure and plot mentions for the inversion workflow
* Synchronous averaging: sqrt(N) figure, diagnostics-tool guidance, See also, recording naming
* Data qualification: runs-test figure with dual snippet and peak-statistics plot mention
* MISO coherence: conditioning-order snippet, practical pitfalls and See also across the three trees
* Time-frequency: Harris window reference and See also across the three trees
* GUM uncertainty: map the domain pages that consume the clause-5 machinery, expand See also
* Filter banks: compliance plot mentions and recording naming in the crossover snippet
* Changelog entry for the core-metrology documentation figures and prose
* Regenerate llms-full.txt for the core-metrology documentation
* Drop the duplicated phase-axis translation key
Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity
Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity
Correct DSP estimator edge cases: TSA time axis, echo detection, EQ validation (#356)
* Report the true 1/fs time axis from time_synchronous_average
The averaged samples sit on the 1/fs sampling grid (each block is aligned
back to it by the band-limited fractional delay before averaging), but the
result reported a time axis with T/M spacing. For a non-integer number of
samples per period the two grids drift apart across the period: with
100.37 samples per period the noiseless recovery error read against the
reported axis was 9.3e-2, versus 2.8e-6 on the true m/fs grid.
Return times = arange(M)/fs, document that the M samples cover the period
only approximately when fs*T is not an integer (McFadden 1987 revised
model: a block average on the sampling grid, no angular resampling), and
assert the non-integer-period tests on the true grid, with a regression
test pinning the 100.37-sample case on both grids. Also soften the comb
response [0, 1] claim (float cancellation beside a tooth can exceed 1 by
a few 1e-9) and mark the ~14 dB N = 32 figure as derived from Eq. 8
rather than printed in the paper.
* Detect inverting echoes and off-sample delays in echo_detection
echo_detection picked the maximum of the signed power cepstrum, so an
inverting reflection (a < 0), whose first rahmonic is a itself and hence
negative, was silently missed: with a = -0.4 at 313 samples the true
rahmonic c[313] = -0.42 was ignored and an unrelated 4739-sample peak
returned. Peak-pick on |cepstrum| within the searched band instead and
report the signed cepstrum value at the peak as the reflection
coefficient (the Mercator series ln(1 + a e^{-j theta}) holds for either
sign of a).
Also refine the reported delay by three-point parabolic interpolation of
|cepstrum| through the peak, so an off-sample delay (e.g. 313.5 samples)
is estimated to a fraction of a sample, and document the bin-splitting
caveat: at off-sample delays the peak-sample coefficient underestimates
|a| (about 65 % of it midway between bins). One-line convention note
distinguishing Milner's IDFT(ln|X|^2) power cepstrum from Bogert's
squared original. Tests cover a < 0 (exact impulse-echo closed form and
a noise source) and the interpolated half-sample delay.
* Validate parametric-EQ sections at the numerical extremes
Three validation gaps in the RBJ cookbook designer:
- A wide 'bw' at an f0 near Nyquist drives the w0/sin(w0) warping factor
into math.sinh overflow, escaping as a raw OverflowError; slightly less
extreme pairs produced a large but finite alpha whose rounded a2 landed
exactly at -1.0: poles on the unit circle designed silently. Wrap the
sinh with an informative ValueError and check the realized coefficients
against the stability triangle (|a2| < 1, |a1| < 1 + a2) after
normalization.
- A shelf slope beyond the gain-dependent bound (A + 1/A)/(A + 1/A - 2)
makes the cookbook's alpha complex and surfaced as a bare 'math domain
error'. Validate the bound at section construction with the limit in
the message (any slope is fine at 0 dB, where A = 1).
- Non-finite f0/gain_db/q/bw/slope passed validation silently (NaN
compares false against every bound) and produced NaN/inf coefficient
rows. Require finiteness explicitly.
Tests cover all three paths plus extreme-but-valid sections that must
keep designing stably.
* Scope the envelope-spectrum amplitude claim and add the band-pass front end
The docstring promised that a sinusoidal modulation 'reads out as a line
at its exact amplitude'; that holds only when the modulation frequency
falls on an analysis bin. Off-bin lines read low by the taper's
scalloping loss (about 1.42 dB, ~15 %, for the default Hann midway
between bins), like any single-record amplitude spectrum. State the
on-bin condition on the closed forms and the caveat in the module,
function and result docstrings, pinned by a midway-between-bins test.
Also add the optional band=(low, high) pre-filter to envelope_spectrum:
a zero-phase 4th-order Butterworth band-pass ahead of the detector, the
band-pass front end of Bendat & Piersol Figure 13.11 and the classical
bearing-envelope chain (isolate the excited resonance band, then
envelope it). The band travels with the result; a test shows it
recovering the exact modulation line under a strong out-of-band
interferer that swamps the raw envelope.
* Warn when a tone burst cannot close on the tone's zero crossing
IEC 60268-1 Clause A2.1 asks for an integral number of full periods, but
the gate closes after round(fs*cycles/frequency) samples: sample-exact
only when f and fs are commensurate. For 10 cycles of 997 Hz at 48 kHz
the burst spans 481.44 samples, gated at 481, and the waveform carries a
residual step at the gate edge. Document the condition and emit a
PhonometryWarning quantifying the realized residual (bounded by
amplitude*sin(pi*f/fs)) for incommensurate pairs; commensurate bursts
stay silent.
Also tighten the resampler's 'equiripple-bounded' wording: the Kaiser
window method bounds both bands by the same delta = 10^(-A/20), but its
ripple decays away from the band edges, unlike a true equiripple design.
* Document estimator conventions verified against their sources
Documentation and comment corrections, no behavior changes:
- random_data: keep the reverse-arrangement acceptance bounds on the
normal approximation deliberately and say why: B&P Table A.6 itself
follows it, and no percentage-point convention on the exact Mahonian
distribution reproduces the published entries (N = 40 and N = 100 at
a = 0.975 pin it down), so exact bounds would disagree with the table
users check against. The p-value stays exact; the one-count boundary
disagreement is now documented on TrendTestResult.
- time_frequency: the spectrogram energy-recovery statement was wrong as
written; integrating 'density' columns over frequency and summing over
time recovers the record energy only after multiplying by the hop
duration, up to the taper roll-off at the record edges (verified
0.988 vs 1 for Hann at 75 % overlap on white noise).
- spectra: note that the adaptive multitaper sigma^2 is mean(x^2) with no
mean removal (consistent with the documented no-detrending
calibration), and mark the 'P&W Eq. 369a' citation as pending
verification against the book.
- compliance + tests/reference_data: transcription note for the bare
'+3' at 20 Hz, Type 2, in ANSI S1.4-1983 Table V (read as upper-only;
+/-3 plausible; either way the verdict cannot change, the realized
deviation is -0.05 dB).
- room_ir: the Mueller & Massarani 'below 4 dB' crest-factor figure
assumes their slight magnitude smoothing, which shaped_sweep_signal
does not implement; measured sweeps here sit at 4.2-4.3 dB.
* Translate EQ section labels, complete the bibliography and changelog
- The per-section legend labels of the parametric-EQ plot printed the raw
English filter-type names in Spanish figures; route them through the
plot string table (peaking -> campana, shelves, band-pass, notch,
all-pass; lowpass/highpass were already translated for the lifter
plot). English output stays byte-identical.
- docs/references.md: add the Harris 1978 window paper and IEC
60268-1:1985, both cited by guide pages but missing from the collected
bibliography; link the IEC entry (and the one in test-signals.md) to
the IEC webstore page.
- Changelog entries for the DSP fixes; regenerate the API reference,
llms-full.txt and the cepstrum_echo figures (the detected-echo marker
moved by the sub-sample delay interpolation); the conformance report is
unchanged (419/419).
* Propagate the echo and envelope semantics to the site guides
Review follow-ups:
- The EN and ES site guides (cepstrum-echoes.mdx) still described the
old echo reading and the unqualified 'exact amplitude' claim; bring
them in step with docs/cepstrum-echoes.md: |cepstrum| peak-picking,
signed coefficient, interpolated delay, bin-splitting caveat, the
on-bin/scalloping condition and the new band= front end (the docs page
gains the same envelope-section text).
- State in the changelog and the result docstring that delay is no
longer exactly delay_samples/fs when the interpolated offset is
nonzero (delay_samples remains the whole-sample index the coefficient
is read at), and merge the duplicated Unreleased headings.
- Clearer stability message (poles 'do not lie strictly inside the unit
circle', full-precision coefficients) and an informative short-record
error for the envelope band-pass pre-filter instead of scipy's padlen
message.
- Sharper tone-burst warning test (asserts the quantified span and
residual) and a tighter interpolated-delay tolerance.
* Address review notes: cepstrum terminology, band-pass claims, edge validation
- Guides (docs and site, EN and ES): call the signed quantity what it is,
Milner's cepstrum of the log-power spectrum, and spell out that
Bogert's original 1963 power cepstrum squares once more and is
non-negative, so the signed rahmonics are the library's documented
convention; qualify the band-pass front end (out-of-band content is
strongly attenuated, not eliminated: finite Butterworth rejection and
small zero-phase edge transients).
- cepstrum: render reflection_coefficient as inline code in the
delay_samples docstring so the generated API page stops linking the
unrelated underwater seabed function.
- envelope: validate that 'band' is exactly two numeric edges before
indexing (a one-item tuple raised IndexError, extra entries were
ignored); the validated edges now travel to the result.
- equalizer: reject finite but unrepresentable gains through a shared
_gain_amplitude helper (10^(gain_db/40) overflowing, or underflowing
to zero and then dividing by zero in the designers); document the 0 dB
exception to the shelf-slope bound on the slope field.
- tone_burst: validate the repetition configuration before emitting the
incommensurate-frequency warning, so invalid setups raise even under
a warnings-as-errors filter.
- comb_filter_response: reject phase products that overflow to infinity
(sin(inf) returned NaN instead of the documented bounded response).
Tests for every new rejection path; API reference and llms regenerated.
* Test the representable gain amplitude as a positive finite bound
* Scope the first-rahmonic height claim to the source-free identity