Geometry drawings: secondary set-ups across building, materials and rooms (#386)
* Geometry drawings: secondary set-ups across building, materials and rooms
Nine more to-scale drawings, each with the realistic dimensions of its
standard rig or textbook case:
- Composite facade elevation with the element areas to scale
(FacadePredictionResult retains its elements).
- Mass-spring-mass double wall: 12,5 mm plasterboard leaves on a
100 mm cavity, resonance annotated (double-wall results retain
mass1/mass2/gap).
- Plate junctions L/T1/T2/X following the junction_transmission
conventions (plate 1 continuous for T1/X, the perpendicular pair
continuous for T2/X); results retain both thicknesses.
- In-situ road absorption set-up: source at 1,25 m, microphone at
0,25 m, the 1,34 m sampled radius of the 5 ms window.
- Dynamic-stiffness resonance rig: 200 mm square specimen under the
8 kg load plate.
- Free-field diffusion goniometer in plan: 37 microphones on the 5 m
arc, source at 10 m.
- Baffled radiating plate (RadiationEfficiencyResult already carries
its geometry).
- Open-plan measurement line with rD/rP marked (OpenPlanResult
retains the microphone positions).
- Face-to-face p-p intensity probe with the 12 mm spacer
(IntensityResult retains the spacing).
Nine public plot_* functions, retention fields on six results
(trailing, defaulted), 36 generated SVG variants embedded in nine
guides (EN/ES and the GitHub mirrors, including the first figures of
the junction-transmission and vibration-sound-power guides), curated
table and generated API pages updated, and 10 new tests.
* Address review: junction alt texts, retained-field docs, small guards
- The T-junction figure alt texts now name T2, matching the drawn
geometry and the runnable example.
- Retained-geometry fields documented on all six result docstrings
(and the generated API pages regenerated).
- plot_facade_elements rejects an explicit zero area instead of
silently substituting the nominal tile, and its kwargs contract now
names the first element rectangle; plot_goniometer_geometry
validates sample_width and documents it in the curated table.
- Facade prose spelling unified with the surrounding sections.
* Drop the identical-in-both-languages unit literal from the translation table
Geometry drawings: devices, measurement layouts and the FDTD domain (#385)
* Geometry drawings: devices, measurement layouts and the FDTD domain
Extends the to-scale geometry API from the materials batch to the
devices and set-ups around them:
- Reactive silencers: side cuts of the expansion chamber (plain and
with extended tubes), the side-branch Helmholtz resonator (cavity
drawn as its equal-volume cube, volume annotated) and the
quarter-wave stub, using equivalent circular diameters 2 sqrt(S/pi).
ReactiveSilencerResult retains its constructor geometry and gains
plot_geometry().
- Image-source room plan: ImageSourceResult.plot_geometry() draws the
mirror-room lattice with images coloured by reflection order (low
orders on top), source and receiver marked.
- Barrier section: direct and diffracted paths over ground with the
path-length difference annotated; BarrierInsertionLoss retains the
five distances/heights and the optional thickness.
- Microphone position arrays: plot_microphone_positions() is the
library's first 3-D drawing (numbered points on a wireframe
hemisphere or sphere with the reflecting plane), fed directly by
measurement_positions()/precision_positions().
- Wall apertures: slit or circular section to scale with transmitted
wavefronts; ApertureTransmissionResult retains width/radius/depth.
- Baffled piston with its normalised far-field lobe at a chosen
frequency (RadiatingPistonResult.plot_geometry()).
- Plenum chamber: the box honours the line of sight r and its angle
exactly; outlet mouth to scale, wall area annotated.
- FDTD domain preview: FDTD2D.plot_geometry() draws the configured
domain before any time stepping (obstacles, sponge layers, impedance
and rigid edges, sources, optional probes); the solver now records
sponge_width, sponge_sides and edge_impedance as public read-only
configuration.
Six new public plot_*_geometry functions, 40 generated SVG variants
embedded in seven guides (EN/ES and the GitHub mirrors) with runnable
snippets, curated table and generated API pages updated, and 14 new
tests (retention round-trips, refusal paths, validation before any
figure is created, 3-D smoke).
* Address review: probes and frequency-index validation, immutable edge record
- plot_fdtd_domain validates probes before any figure exists.
- RadiatingPistonResult.plot_geometry bounds-checks frequency_index
with a descriptive ValueError.
- FDTD2D.edge_impedance is a MappingProxyType over a private copy.
- Plenum kwargs docstring matches where they are forwarded; the FDTD
preview prose no longer claims source-in-obstacle catching (the
solver already rejects that at add_source).
* Address static analysis: shared constants, extracted helpers, flat calls
- Silencer kinds, axis labels, legend placement and repeated messages
hoisted into module constants; identical EN/ES strings dropped from
the translation table.
- plot_silencer_geometry split into per-kind validators (and its
artist kwargs removed, matching the geometry-dict entry point);
_draw_hr_cavity and the FDTD sponge/edge painters extracted.
- Aperture opening computed without a nested conditional; exception
tests build their arrays outside pytest.raises.
- Regenerated API pages for the touched docstrings.
* Split the side-branch dimension resolution out of the drawing routine
Keeps _draw_branch_silencer under the cognitive-complexity threshold;
drawing output unchanged.
Geometry drawings: secondary set-ups across building, materials and rooms (#386)
* Geometry drawings: secondary set-ups across building, materials and rooms
Nine more to-scale drawings, each with the realistic dimensions of its
standard rig or textbook case:
- Composite facade elevation with the element areas to scale
(FacadePredictionResult retains its elements).
- Mass-spring-mass double wall: 12,5 mm plasterboard leaves on a
100 mm cavity, resonance annotated (double-wall results retain
mass1/mass2/gap).
- Plate junctions L/T1/T2/X following the junction_transmission
conventions (plate 1 continuous for T1/X, the perpendicular pair
continuous for T2/X); results retain both thicknesses.
- In-situ road absorption set-up: source at 1,25 m, microphone at
0,25 m, the 1,34 m sampled radius of the 5 ms window.
- Dynamic-stiffness resonance rig: 200 mm square specimen under the
8 kg load plate.
- Free-field diffusion goniometer in plan: 37 microphones on the 5 m
arc, source at 10 m.
- Baffled radiating plate (RadiationEfficiencyResult already carries
its geometry).
- Open-plan measurement line with rD/rP marked (OpenPlanResult
retains the microphone positions).
- Face-to-face p-p intensity probe with the 12 mm spacer
(IntensityResult retains the spacing).
Nine public plot_* functions, retention fields on six results
(trailing, defaulted), 36 generated SVG variants embedded in nine
guides (EN/ES and the GitHub mirrors, including the first figures of
the junction-transmission and vibration-sound-power guides), curated
table and generated API pages updated, and 10 new tests.
* Address review: junction alt texts, retained-field docs, small guards
- The T-junction figure alt texts now name T2, matching the drawn
geometry and the runnable example.
- Retained-geometry fields documented on all six result docstrings
(and the generated API pages regenerated).
- plot_facade_elements rejects an explicit zero area instead of
silently substituting the nominal tile, and its kwargs contract now
names the first element rectangle; plot_goniometer_geometry
validates sample_width and documents it in the curated table.
- Facade prose spelling unified with the surrounding sections.
* Drop the identical-in-both-languages unit literal from the translation table
Follow the ANSI/ASA S12.2-2019 5.2.2 NC procedure and tighten the room fiches (#354)
Rate NC spectra by the standard's two-step procedure (5.2.2): the speech
interference level (clause 3.2, the average of the 500/1000/2000/4000 Hz
octave-band levels) selects the NC-(SIL) curve and the spectrum is
designated NC-(SIL) unless an octave band exceeds it, in which case the
tangency method (5.2.3) applies. NCResult gains sil, tangency_rating,
method, out_of_range and a label property; the tangency rating stays
available on every in-family result. Spectra outside the NC-15 to NC-70
family of Table 1 are flagged out of range instead of clamping the
interpolation to fabricated NC-71/NC-14 designations: above the family
the governing band is the maximum exceedance over the NC-70 curve and the
label reads ">NC-70 (band)"; below it, "<NC-15". Fiche, plot and
verdict render the flagged designation in English and Spanish.
On the RC Mark II side, warn when the clause D.4 minimum band set
(31.5 Hz through 4000 Hz) is incomplete, flag ratings outside the
tabulated RC-25 to RC-50 family (Table D.1) with an extrapolation note on
the fiche, and document the combined RH tag as a diagnostic extension
beyond the clause D.3.5 letters (N, R, H, RV; the RV vibration/rattle
classification needs the Table 6 test and is not implemented).
On the ISO 3382-1/-2 fiche, label the mid-frequency descriptor honestly
for one-third-octave data (only the 500 Hz and 1 kHz one-third-octave
bands are averaged, so the octave "500-1000 Hz" claim is dropped and the
bands are named), name the band of a fallback T30/EDT descriptor when the
range does not span both mid bands, and choose the EDT_mid vs EDT label
from EDT's own band coverage instead of T30's. Fiche verdicts (ISO 3382
and S12.2) now compare display-rounded values so the printed numbers can
never contradict the verdict at a tolerance boundary.
Correct two citations in the room-acoustics docstrings: the 5 %
reverberation-time JND is ISO 3382-1:2009 Table A.1 (ISO 3382-2:2008
Table A.1 tabulates the uncertainty constants G and H) and the -20 dB
onset trigger is ISO 3382-1:2009 A.3.4, with a note on the at-edge
sample choice. English ISO 3382-3 strings use point decimals
(STI = 0.50/0.20); the Spanish strings keep the comma.
Docs (EN/ES), API reference, conformance check, changelog and the
affected example fiches are updated accordingly.
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
Follow the ANSI/ASA S12.2-2019 5.2.2 NC procedure and tighten the room fiches (#354)
Rate NC spectra by the standard's two-step procedure (5.2.2): the speech
interference level (clause 3.2, the average of the 500/1000/2000/4000 Hz
octave-band levels) selects the NC-(SIL) curve and the spectrum is
designated NC-(SIL) unless an octave band exceeds it, in which case the
tangency method (5.2.3) applies. NCResult gains sil, tangency_rating,
method, out_of_range and a label property; the tangency rating stays
available on every in-family result. Spectra outside the NC-15 to NC-70
family of Table 1 are flagged out of range instead of clamping the
interpolation to fabricated NC-71/NC-14 designations: above the family
the governing band is the maximum exceedance over the NC-70 curve and the
label reads ">NC-70 (band)"; below it, "<NC-15". Fiche, plot and
verdict render the flagged designation in English and Spanish.
On the RC Mark II side, warn when the clause D.4 minimum band set
(31.5 Hz through 4000 Hz) is incomplete, flag ratings outside the
tabulated RC-25 to RC-50 family (Table D.1) with an extrapolation note on
the fiche, and document the combined RH tag as a diagnostic extension
beyond the clause D.3.5 letters (N, R, H, RV; the RV vibration/rattle
classification needs the Table 6 test and is not implemented).
On the ISO 3382-1/-2 fiche, label the mid-frequency descriptor honestly
for one-third-octave data (only the 500 Hz and 1 kHz one-third-octave
bands are averaged, so the octave "500-1000 Hz" claim is dropped and the
bands are named), name the band of a fallback T30/EDT descriptor when the
range does not span both mid bands, and choose the EDT_mid vs EDT label
from EDT's own band coverage instead of T30's. Fiche verdicts (ISO 3382
and S12.2) now compare display-rounded values so the printed numbers can
never contradict the verdict at a tolerance boundary.
Correct two citations in the room-acoustics docstrings: the 5 %
reverberation-time JND is ISO 3382-1:2009 Table A.1 (ISO 3382-2:2008
Table A.1 tabulates the uncertainty constants G and H) and the -20 dB
onset trigger is ISO 3382-1:2009 A.3.4, with a note on the at-edge
sample choice. English ISO 3382-3 strings use point decimals
(STI = 0.50/0.20); the Spanish strings keep the comma.
Docs (EN/ES), API reference, conformance check, changelog and the
affected example fiches are updated accordingly.