feat: floor-covering impact improvement on a mock-up (ISO 16251-1:2014) (#130)
Add the laboratory method for the improvement of impact sound insulation ΔL of
soft, locally-reacting floor coverings (carpet, PVC, linoleum) measured on a
small concrete mock-up via structure-borne acceleration levels, plus the
ISO 717-2 weighted improvement ΔLw it feeds.
- weighted_impact_improvement (insulation.py): ISO 717-2:2020 Clause 5 ΔLw =
78 - Ln,r,w using the heavyweight reference floor of Table 4, reusing the
verified weighted_impact_rating engine
- floor_covering_improvement.py (ISO 16251-1):
- acceleration_level (Formula 1, a0 = 1e-6 m/s²)
- background_corrected_level (Formula 2, three-branch rule with a
limit-of-measurement flag)
- impact_improvement: Formula (2) per position -> difference (3) -> mean over
positions (4); accepts (bands,) or (positions, bands) levels
- improvement_octave_bands (Formula 5)
- FloorCoveringImprovementResult with ΔLw, the > ΔL limit mask and .plot()
- Conformance checks: ISO 717-2 reference-floor rating (78 dB, CI -11) and the
ΔL=0 -> ΔLw=0 identity (109/109). ISO 16251-1 has no worked numeric example
(Annex B is a blank form), so the oracle is the ISO 717-2 reference floor.
- generate_floor_covering_improvement figure (EN/ES × light/dark)
- Building-acoustics guide §7 and API reference rows (EN + ES)
- 20 tests covering all formulas, the per-position ordering and validation
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Audit pass 11b: Tier-1 documentation animations (#122)
* Audit pass 11b: Tier-1 documentation animations
Add the four Tier-1 animation clips the audit prioritised — level-vs-time
phenomena the library already computes, rendered deterministically by
generate_graphs.py:
- time-weighting ballistics: the Fast/Slow/Impulse detectors chasing a tone
burst, Impulse decaying slowest (IEC 61672-1);
- onset detection: an L_AF history with the >10 dB/s onset highlighted and
OR/LD/P/KI shown live (NT ACOU 112);
- instantaneous intensity: p·u flowing for a progressive wave vs sloshing
about zero for a standing wave (IEC 61043);
- Schroeder backward integration: the decay curve emerging from the tail,
ending with the T20/T30 lines (ISO 3382).
Each is produced in the four language x theme variants as a compact WebM for
the site (embedded as an autoplaying, looping <video>) and, for English, an
animated GIF for the GitHub docs. A new `_translate_str` localises the
per-frame labels (the clips never pass through themed_path), the site gains
<video> theme-switching CSS, and `make animations` (kept out of CI, since
video is not byte-reproducible) regenerates them.
* Address review of the animations PR
- generate_animations: fail fast with a clear message when ffmpeg is absent
(Gemini).
- Schroeder _fit: guard against fewer than two points in a T20/T30 range and
a non-decaying slope, and keep xmax robust when a fit is unavailable
(Copilot).
- Site <video>s: add native `controls` (a keyboard-accessible pause/stop for
the looping motion, WCAG 2.2.2) and move the description to `title`, dropping
the `role="img"`/`aria-label` pair so the controls stay exposed to assistive
tech (CodeRabbit).
- Spanish: "energy sloshes" -> "la energía va y viene" (technical register;
ES intensity clips regenerated) (CodeRabbit).
- Group `no-autoplay` with the other `no-*` html-validate rules (CodeRabbit).
* Fix stale 'no controls' comment in theme-images.css
The Tier-1 <video>s now carry native controls; update the shared CSS comment
to match (CodeRabbit).
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
EN 12354-6: sound absorption in enclosed spaces (#107)
* feat: EN 12354-6 sound absorption in enclosed spaces
Add the EN 12354-6:2003 prediction of a room's total equivalent sound
absorption area and reverberation time from the absorption of its
surfaces and objects (the normative Clause 4 model).
The absorption area sums the surface contributions, the object areas and
the air absorption (Formula 1), with the air term Aair = 4*m*V*(1 - psi)
(Formula 2, Table 1), the object fraction psi = sum(Vobj)/V (Formula 3)
and the empirical hard-object area Aobj = Vobj^(2/3) (Formula 4). The
reverberation time follows as T = 55.3/c0 * V*(1 - psi)/A (Formula 5,
the 0.16 factor at c0 = 345.6 m/s). The informative Annex D method for
irregular spaces is out of scope.
New module phonometry.en12354_6 with equivalent_absorption_area,
object_fraction, hard_object_absorption, air_absorption_area,
reverberation_time and the per-band enclosed_space_reverberation
returning a ReverberationResult with .plot(). Conformance report gains
an enclosed-space absorption domain (2 checks, 90 total). Adds the
enclosed-space-absorption guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated digit-exact against the three worked cases of Annex E
(A = 2.26/5.03/10.21 m2, T = 2.1/0.9/0.5 s, and the air-absorption
note Aair = 0.12 m2 -> T = 2.0 s).
* refactor: address review feedback on EN 12354-6
- validation helpers _require_positive/_require_fraction: single error
literal and no negated comparison, still rejecting NaN (SonarCloud
S1192/S1940)
- object_fraction: reject negative object volumes and a fraction >= 1
(Gemini)
- air_absorption_area: validate the object fraction range and a
non-negative attenuation coefficient (Gemini)
- equivalent_absorption_area: reject negative air_area, absorption
coefficients and object areas (Gemini)
- reverberation_time: validate the object fraction range (Gemini)
- enclosed_space_reverberation: clear error when a built-in
air_condition is combined with non-standard frequencies (Gemini)
- diagram + alt text: the speed-of-sound symbol is c0, not co
(CodeRabbit); the diagram now renders it as a proper subscript
- tests: cover the speed_of_sound guard (CodeRabbit), NaN volume, the
physical-range validations and the standard-bands guard
* docs: label the object-array sum in the Formula 1 prose
The third summand of Formula 1 is the standard's object arrays k
(groups of identical objects treated as an absorbing surface), not a
duplicated surface term; name all three indices in the surrounding
prose so the equation reads unambiguously (CodeRabbit).
EN 12354-6: sound absorption in enclosed spaces (#107)
* feat: EN 12354-6 sound absorption in enclosed spaces
Add the EN 12354-6:2003 prediction of a room's total equivalent sound
absorption area and reverberation time from the absorption of its
surfaces and objects (the normative Clause 4 model).
The absorption area sums the surface contributions, the object areas and
the air absorption (Formula 1), with the air term Aair = 4*m*V*(1 - psi)
(Formula 2, Table 1), the object fraction psi = sum(Vobj)/V (Formula 3)
and the empirical hard-object area Aobj = Vobj^(2/3) (Formula 4). The
reverberation time follows as T = 55.3/c0 * V*(1 - psi)/A (Formula 5,
the 0.16 factor at c0 = 345.6 m/s). The informative Annex D method for
irregular spaces is out of scope.
New module phonometry.en12354_6 with equivalent_absorption_area,
object_fraction, hard_object_absorption, air_absorption_area,
reverberation_time and the per-band enclosed_space_reverberation
returning a ReverberationResult with .plot(). Conformance report gains
an enclosed-space absorption domain (2 checks, 90 total). Adds the
enclosed-space-absorption guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated digit-exact against the three worked cases of Annex E
(A = 2.26/5.03/10.21 m2, T = 2.1/0.9/0.5 s, and the air-absorption
note Aair = 0.12 m2 -> T = 2.0 s).
* refactor: address review feedback on EN 12354-6
- validation helpers _require_positive/_require_fraction: single error
literal and no negated comparison, still rejecting NaN (SonarCloud
S1192/S1940)
- object_fraction: reject negative object volumes and a fraction >= 1
(Gemini)
- air_absorption_area: validate the object fraction range and a
non-negative attenuation coefficient (Gemini)
- equivalent_absorption_area: reject negative air_area, absorption
coefficients and object areas (Gemini)
- reverberation_time: validate the object fraction range (Gemini)
- enclosed_space_reverberation: clear error when a built-in
air_condition is combined with non-standard frequencies (Gemini)
- diagram + alt text: the speed-of-sound symbol is c0, not co
(CodeRabbit); the diagram now renders it as a proper subscript
- tests: cover the speed_of_sound guard (CodeRabbit), NaN volume, the
physical-range validations and the standard-bands guard
* docs: label the object-array sum in the Formula 1 prose
The third summand of Formula 1 is the standard's object arrays k
(groups of identical objects treated as an absorbing surface), not a
duplicated surface term; name all three indices in the surrounding
prose so the equation reads unambiguously (CodeRabbit).
EN 12354-6: sound absorption in enclosed spaces (#107)
* feat: EN 12354-6 sound absorption in enclosed spaces
Add the EN 12354-6:2003 prediction of a room's total equivalent sound
absorption area and reverberation time from the absorption of its
surfaces and objects (the normative Clause 4 model).
The absorption area sums the surface contributions, the object areas and
the air absorption (Formula 1), with the air term Aair = 4*m*V*(1 - psi)
(Formula 2, Table 1), the object fraction psi = sum(Vobj)/V (Formula 3)
and the empirical hard-object area Aobj = Vobj^(2/3) (Formula 4). The
reverberation time follows as T = 55.3/c0 * V*(1 - psi)/A (Formula 5,
the 0.16 factor at c0 = 345.6 m/s). The informative Annex D method for
irregular spaces is out of scope.
New module phonometry.en12354_6 with equivalent_absorption_area,
object_fraction, hard_object_absorption, air_absorption_area,
reverberation_time and the per-band enclosed_space_reverberation
returning a ReverberationResult with .plot(). Conformance report gains
an enclosed-space absorption domain (2 checks, 90 total). Adds the
enclosed-space-absorption guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated digit-exact against the three worked cases of Annex E
(A = 2.26/5.03/10.21 m2, T = 2.1/0.9/0.5 s, and the air-absorption
note Aair = 0.12 m2 -> T = 2.0 s).
* refactor: address review feedback on EN 12354-6
- validation helpers _require_positive/_require_fraction: single error
literal and no negated comparison, still rejecting NaN (SonarCloud
S1192/S1940)
- object_fraction: reject negative object volumes and a fraction >= 1
(Gemini)
- air_absorption_area: validate the object fraction range and a
non-negative attenuation coefficient (Gemini)
- equivalent_absorption_area: reject negative air_area, absorption
coefficients and object areas (Gemini)
- reverberation_time: validate the object fraction range (Gemini)
- enclosed_space_reverberation: clear error when a built-in
air_condition is combined with non-standard frequencies (Gemini)
- diagram + alt text: the speed-of-sound symbol is c0, not co
(CodeRabbit); the diagram now renders it as a proper subscript
- tests: cover the speed_of_sound guard (CodeRabbit), NaN volume, the
physical-range validations and the standard-bands guard
* docs: label the object-array sum in the Formula 1 prose
The third summand of Formula 1 is the standard's object arrays k
(groups of identical objects treated as an absorbing surface), not a
duplicated surface term; name all three indices in the surrounding
prose so the equation reads unambiguously (CodeRabbit).
EN 12354-6: sound absorption in enclosed spaces (#107)
* feat: EN 12354-6 sound absorption in enclosed spaces
Add the EN 12354-6:2003 prediction of a room's total equivalent sound
absorption area and reverberation time from the absorption of its
surfaces and objects (the normative Clause 4 model).
The absorption area sums the surface contributions, the object areas and
the air absorption (Formula 1), with the air term Aair = 4*m*V*(1 - psi)
(Formula 2, Table 1), the object fraction psi = sum(Vobj)/V (Formula 3)
and the empirical hard-object area Aobj = Vobj^(2/3) (Formula 4). The
reverberation time follows as T = 55.3/c0 * V*(1 - psi)/A (Formula 5,
the 0.16 factor at c0 = 345.6 m/s). The informative Annex D method for
irregular spaces is out of scope.
New module phonometry.en12354_6 with equivalent_absorption_area,
object_fraction, hard_object_absorption, air_absorption_area,
reverberation_time and the per-band enclosed_space_reverberation
returning a ReverberationResult with .plot(). Conformance report gains
an enclosed-space absorption domain (2 checks, 90 total). Adds the
enclosed-space-absorption guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated digit-exact against the three worked cases of Annex E
(A = 2.26/5.03/10.21 m2, T = 2.1/0.9/0.5 s, and the air-absorption
note Aair = 0.12 m2 -> T = 2.0 s).
* refactor: address review feedback on EN 12354-6
- validation helpers _require_positive/_require_fraction: single error
literal and no negated comparison, still rejecting NaN (SonarCloud
S1192/S1940)
- object_fraction: reject negative object volumes and a fraction >= 1
(Gemini)
- air_absorption_area: validate the object fraction range and a
non-negative attenuation coefficient (Gemini)
- equivalent_absorption_area: reject negative air_area, absorption
coefficients and object areas (Gemini)
- reverberation_time: validate the object fraction range (Gemini)
- enclosed_space_reverberation: clear error when a built-in
air_condition is combined with non-standard frequencies (Gemini)
- diagram + alt text: the speed-of-sound symbol is c0, not co
(CodeRabbit); the diagram now renders it as a proper subscript
- tests: cover the speed_of_sound guard (CodeRabbit), NaN volume, the
physical-range validations and the standard-bands guard
* docs: label the object-array sum in the Formula 1 prose
The third summand of Formula 1 is the standard's object arrays k
(groups of identical objects treated as an absorbing surface), not a
duplicated surface term; name all three indices in the surrounding
prose so the equation reads unambiguously (CodeRabbit).
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Building acoustics II: facade insulation (ISO 16283-3), laboratory measurement (ISO 10140), prediction with flanking (EN 12354) and uncertainty (ISO 12999-1) (#88)
* feat: ISO 16283-3 facade sound insulation
Add facade_insulation() and FacadeInsulationResult for field facade sound
insulation per ISO 16283-3: the global-method level difference D2m and its
standardized (D2m,nT) and normalized (D2m,n) forms, plus the element-method
apparent sound reduction index R'45 (loudspeaker, -1,5 dB) / R'tr,s (road
traffic, -3 dB). Reuses the ISO 16283-1 energy-averaging helpers, the
Sabine absorption area, and the ISO 717-1 airborne weighted_rating engine
unchanged for the single-number rating. Adds a per-band .plot() profile and
exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 16283-3 draft-edition caveat and symmetric R' validation
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 10140 laboratory airborne and impact sound insulation
Add src/phonometry/lab_insulation.py, the laboratory counterpart of the
field ISO 16283 family:
- lab_airborne_insulation: R = L1 - L2 + 10 lg(S/A) with A = 0,16 V/T
(ISO 10140-2:2010 Formula (2); ISO 10140-4:2010 Formula (5)).
- lab_impact_insulation: Ln = Li + 10 lg(A/A0), A0 = 10 m²
(ISO 10140-3:2010 Formula (1)).
- background_correction: ISO 10140-4:2010 Clause 4.3 Formula (4) with the
6/15 dB criteria and the 1,3 dB limit-of-measurement cap.
Single-number Rw / Ln,w with C, Ctr, CI reuse the verified ISO 717-1/2
weighted_rating / weighted_impact_rating engines; position energy
averaging reuses _as_band_levels. 29 new closed-form / identity tests.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reconcile facade citations with published ISO 16283-3:2016
The facade module was drafted from ISO/DIS 16283-3:2014; its docstrings
cited draft formula numbers with a caveat to reconcile against the
published edition. Reconciled against ISO 16283-3:2016(E) (First edition
2016-02-01):
- Clause numbers are edition-stable: the field-quantity definitions keep
3.12 (R'45deg), 3.13 (R'tr,s), 3.14 (D2m), 3.15 (D2m,nT), 3.16 (D2m,n),
3.17 (A=0,16V/T), and 9.5.1 (surface-level averaging).
- Formula numbers differ: in the 2016 edition the Clause 3 defining
formulas are UNNUMBERED (inline in the term definitions); the numbered
formulas (1)-(21) live in the procedural clauses. The surface-level
energy-average is Formula (7) in 2016 (was Formula (20) in the DIS).
- Dropped the invalid draft Formula (2)-(7) citations from the field-
quantity docstrings and the draft-edition reconciliation caveat.
- Constants and formula bodies are unchanged (-1,5 dB / -3 dB, A0=10 m2,
T0=0,5 s, A=0,16V/T, band ranges): no numeric change; 22 facade tests
green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: EN 12354-1/2 building acoustic performance prediction with flanking
Implement the EN 12354:2000 simplified single-number prediction model for
apparent airborne (R'w) and impact (L'n,w) sound insulation, including direct
plus flanking transmission (Ff/Df/Fd paths) and the Annex E vibration-reduction
index Kij for rigid cross, rigid T, flexible-interlayer and lightweight-facade
junctions.
Airborne Formula (26)/(27)/(28a) with l0=1 m, Kij,min (29), lining composition
(30)/(31); impact Formula (21) with bare-floor Ln,w,eq (164-35 lg m'), Table 1
flanking correction K, and standardized L'nT,w (3). Results expose per-path
energy contributions so the dominant flanking path is visible.
Validated against the standards' worked examples: Part 1 Annex H.3 airborne
(R'w = 52 dB, 13 paths; +floating-floor 53 dB) and Part 2 Annex E.3 impact
(L'n,w = 45 dB, L'nT,w = 43 dB); all four Annex H junctions reproduce Kij.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 12999-1 building acoustics measurement uncertainty
Add building_uncertainty module implementing ISO 12999-1:2020 standard
uncertainties for sound-insulation quantities: per-band and single-number
values for airborne (Tables 2/3), impact (Tables 4/5) and floor-covering
reduction (Tables 6/7), across measurement situations A/B/C (Clause 5.2),
plus the Annex D sigma_R95 upper limits, Table 1 max repeatability and
Table 8 coverage factors.
Expansion U = k*u with k >= 1 (Clause 8), one-sided factors for conformity
checks (Formulae 4/5), and combination rules from Annexes A/B/C (prediction
input A.1, quadrature A.2/C.2, m-measurement reduction A.7, uncorrelated
single-number B.2). Composable UncertainValue attaches value +- U without
touching the rating dataclasses.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: numpy-stub-agnostic annotations for the two env-dependent mypy sites
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: PR-B review minors — anchors, Kij floor, uncertainty polish
- Table 3 r_w+ctr_50_5000 σsitu(B)=1.0 verified digit-by-digit against the
ISO 12999-1:2020(E) page image; anomalous but normative (comment added).
- Anchor the ISO 10140 rating tests to independent literals (Rw=54, Ln,w=58 —
reference-curve shape + the 32 dB / 16-band = 2 dB ISO 717 shift).
- background_correction: cross-ref sound_power.background_noise_correction and
document the negative-margin (Lb > Lsb) cap at Lsb−1.3.
- flanking_path: optional kij_min clamp for EN 12354-1 Clause 4.4.2 (Kij≥Kij,min),
documented on flanking_element; tested clamped vs unclamped (H.3 unaffected).
- impact_flanking_correction: comment on nearest-neighbour + tie-to-lower.
- Export COVERAGE_FACTORS (Table 8) as public API.
- single_number_uncertainty: note impact situation A is an estimate (Table 5 fn a).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: conformance checks for facade, lab insulation, EN 12354 and ISO 12999
Add six numerical conformance checks for the PR-B building-acoustics
standards, following the established registry pattern (single source of
truth in tests/reference_data.py, clause citations, honest tolerances):
- ISO 16283-3:2016 Clause 3.12: facade R'45 isolates the -1.5 dB
oblique-incidence correction on an S=A constructed case (exact).
- ISO 10140-2:2021 Formula (2): lab airborne R laid on the ISO 717-1
reference shape (S=A) -> Rw = 54 (the +2-shift analytic anchor).
- EN 12354-1:2000 Annex H.3: airborne prediction R'w = 52 from the 13
transmission paths (direct + 12 flanking), the branch's strongest oracle.
- EN 12354-2:2000 Annex E.3: impact prediction L'n,w = 45 (76-33+2).
- ISO 12999-1:2020 Table 2: airborne band uncertainty, situation A @
1 kHz = 1.8 dB (digit-exact), and Clause 8/Table 8 expanded
uncertainty U = 1.96 u = 2.352 dB (exact k=1.96 arithmetic).
Facade and lab checks join "Room & building acoustics"; the EN 12354 /
ISO 12999 checks form a new "Building prediction & uncertainty" domain.
Registry grows 26 -> 32 checks across 7 domains. Shared expected values
and the Annex H.3 input table move into reference_data.py so the report
and tests cannot drift; a consistency test pins them to the published
worked-example results. docs/CONFORMANCE.md regenerated via make conformance.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: building acoustics II — facade, laboratory, prediction and uncertainty (EN)
Extend the Room & Building Acoustics guide with facade insulation
(ISO 16283-3), laboratory characterisation (ISO 10140), flanking-transmission
performance prediction (EN 12354-1/2) and measurement uncertainty
(ISO 12999-1), with executed snippets reproducing the EN 12354-1 Annex H.3
(R'w = 52 dB) and Annex E.3 (L'n,w = 45 dB) worked examples. Add the matching
theory subsections, API-reference rows for every new public name, README and
landing-page entries (29 -> 33 standards), and CHANGELOG. EN docs and site
twins keep byte-identical code blocks.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: flanking-paths diagram, prediction and uncertainty figures
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de edificación II (fachadas, laboratorio, predicción, incertidumbre)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: PR-B final-review fixes — count, GitHub-safe math, edition alignment
Landing count corrected to 34 standards (slash-part convention); the
GitHub-unsafe math spacing tokens reintroduced by the new building
sections are scrubbed from the docs/ tree and its site twins; the whole
ISO 10140-2 citation chain aligned to the verified :2010 edition; plus
the six minor documentation-precision fixes from the final review.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 88 review round 1 — isfinite idiom, heading levels, frequencies validation
- building_prediction._check_finite: replace 'v != v or v in (inf,-inf)'
NaN idiom with math.isfinite for SonarCloud (same behavior, cleaner).
- room-acoustics docs (EN docs + site, ES site): relevel the three
parameter-table headings that skipped H2->H4 to H3 (MD001).
- insulation.facade_insulation: validate 'frequencies' length against the
band count, raising a clear ValueError instead of deferring a matplotlib
shape error to plot(). lab_insulation/building_uncertainty have no such
gap (no user-supplied frequencies stored). Regenerated llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Building acoustics II: facade insulation (ISO 16283-3), laboratory measurement (ISO 10140), prediction with flanking (EN 12354) and uncertainty (ISO 12999-1) (#88)
* feat: ISO 16283-3 facade sound insulation
Add facade_insulation() and FacadeInsulationResult for field facade sound
insulation per ISO 16283-3: the global-method level difference D2m and its
standardized (D2m,nT) and normalized (D2m,n) forms, plus the element-method
apparent sound reduction index R'45 (loudspeaker, -1,5 dB) / R'tr,s (road
traffic, -3 dB). Reuses the ISO 16283-1 energy-averaging helpers, the
Sabine absorption area, and the ISO 717-1 airborne weighted_rating engine
unchanged for the single-number rating. Adds a per-band .plot() profile and
exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 16283-3 draft-edition caveat and symmetric R' validation
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 10140 laboratory airborne and impact sound insulation
Add src/phonometry/lab_insulation.py, the laboratory counterpart of the
field ISO 16283 family:
- lab_airborne_insulation: R = L1 - L2 + 10 lg(S/A) with A = 0,16 V/T
(ISO 10140-2:2010 Formula (2); ISO 10140-4:2010 Formula (5)).
- lab_impact_insulation: Ln = Li + 10 lg(A/A0), A0 = 10 m²
(ISO 10140-3:2010 Formula (1)).
- background_correction: ISO 10140-4:2010 Clause 4.3 Formula (4) with the
6/15 dB criteria and the 1,3 dB limit-of-measurement cap.
Single-number Rw / Ln,w with C, Ctr, CI reuse the verified ISO 717-1/2
weighted_rating / weighted_impact_rating engines; position energy
averaging reuses _as_band_levels. 29 new closed-form / identity tests.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reconcile facade citations with published ISO 16283-3:2016
The facade module was drafted from ISO/DIS 16283-3:2014; its docstrings
cited draft formula numbers with a caveat to reconcile against the
published edition. Reconciled against ISO 16283-3:2016(E) (First edition
2016-02-01):
- Clause numbers are edition-stable: the field-quantity definitions keep
3.12 (R'45deg), 3.13 (R'tr,s), 3.14 (D2m), 3.15 (D2m,nT), 3.16 (D2m,n),
3.17 (A=0,16V/T), and 9.5.1 (surface-level averaging).
- Formula numbers differ: in the 2016 edition the Clause 3 defining
formulas are UNNUMBERED (inline in the term definitions); the numbered
formulas (1)-(21) live in the procedural clauses. The surface-level
energy-average is Formula (7) in 2016 (was Formula (20) in the DIS).
- Dropped the invalid draft Formula (2)-(7) citations from the field-
quantity docstrings and the draft-edition reconciliation caveat.
- Constants and formula bodies are unchanged (-1,5 dB / -3 dB, A0=10 m2,
T0=0,5 s, A=0,16V/T, band ranges): no numeric change; 22 facade tests
green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: EN 12354-1/2 building acoustic performance prediction with flanking
Implement the EN 12354:2000 simplified single-number prediction model for
apparent airborne (R'w) and impact (L'n,w) sound insulation, including direct
plus flanking transmission (Ff/Df/Fd paths) and the Annex E vibration-reduction
index Kij for rigid cross, rigid T, flexible-interlayer and lightweight-facade
junctions.
Airborne Formula (26)/(27)/(28a) with l0=1 m, Kij,min (29), lining composition
(30)/(31); impact Formula (21) with bare-floor Ln,w,eq (164-35 lg m'), Table 1
flanking correction K, and standardized L'nT,w (3). Results expose per-path
energy contributions so the dominant flanking path is visible.
Validated against the standards' worked examples: Part 1 Annex H.3 airborne
(R'w = 52 dB, 13 paths; +floating-floor 53 dB) and Part 2 Annex E.3 impact
(L'n,w = 45 dB, L'nT,w = 43 dB); all four Annex H junctions reproduce Kij.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 12999-1 building acoustics measurement uncertainty
Add building_uncertainty module implementing ISO 12999-1:2020 standard
uncertainties for sound-insulation quantities: per-band and single-number
values for airborne (Tables 2/3), impact (Tables 4/5) and floor-covering
reduction (Tables 6/7), across measurement situations A/B/C (Clause 5.2),
plus the Annex D sigma_R95 upper limits, Table 1 max repeatability and
Table 8 coverage factors.
Expansion U = k*u with k >= 1 (Clause 8), one-sided factors for conformity
checks (Formulae 4/5), and combination rules from Annexes A/B/C (prediction
input A.1, quadrature A.2/C.2, m-measurement reduction A.7, uncorrelated
single-number B.2). Composable UncertainValue attaches value +- U without
touching the rating dataclasses.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: numpy-stub-agnostic annotations for the two env-dependent mypy sites
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: PR-B review minors — anchors, Kij floor, uncertainty polish
- Table 3 r_w+ctr_50_5000 σsitu(B)=1.0 verified digit-by-digit against the
ISO 12999-1:2020(E) page image; anomalous but normative (comment added).
- Anchor the ISO 10140 rating tests to independent literals (Rw=54, Ln,w=58 —
reference-curve shape + the 32 dB / 16-band = 2 dB ISO 717 shift).
- background_correction: cross-ref sound_power.background_noise_correction and
document the negative-margin (Lb > Lsb) cap at Lsb−1.3.
- flanking_path: optional kij_min clamp for EN 12354-1 Clause 4.4.2 (Kij≥Kij,min),
documented on flanking_element; tested clamped vs unclamped (H.3 unaffected).
- impact_flanking_correction: comment on nearest-neighbour + tie-to-lower.
- Export COVERAGE_FACTORS (Table 8) as public API.
- single_number_uncertainty: note impact situation A is an estimate (Table 5 fn a).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: conformance checks for facade, lab insulation, EN 12354 and ISO 12999
Add six numerical conformance checks for the PR-B building-acoustics
standards, following the established registry pattern (single source of
truth in tests/reference_data.py, clause citations, honest tolerances):
- ISO 16283-3:2016 Clause 3.12: facade R'45 isolates the -1.5 dB
oblique-incidence correction on an S=A constructed case (exact).
- ISO 10140-2:2021 Formula (2): lab airborne R laid on the ISO 717-1
reference shape (S=A) -> Rw = 54 (the +2-shift analytic anchor).
- EN 12354-1:2000 Annex H.3: airborne prediction R'w = 52 from the 13
transmission paths (direct + 12 flanking), the branch's strongest oracle.
- EN 12354-2:2000 Annex E.3: impact prediction L'n,w = 45 (76-33+2).
- ISO 12999-1:2020 Table 2: airborne band uncertainty, situation A @
1 kHz = 1.8 dB (digit-exact), and Clause 8/Table 8 expanded
uncertainty U = 1.96 u = 2.352 dB (exact k=1.96 arithmetic).
Facade and lab checks join "Room & building acoustics"; the EN 12354 /
ISO 12999 checks form a new "Building prediction & uncertainty" domain.
Registry grows 26 -> 32 checks across 7 domains. Shared expected values
and the Annex H.3 input table move into reference_data.py so the report
and tests cannot drift; a consistency test pins them to the published
worked-example results. docs/CONFORMANCE.md regenerated via make conformance.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: building acoustics II — facade, laboratory, prediction and uncertainty (EN)
Extend the Room & Building Acoustics guide with facade insulation
(ISO 16283-3), laboratory characterisation (ISO 10140), flanking-transmission
performance prediction (EN 12354-1/2) and measurement uncertainty
(ISO 12999-1), with executed snippets reproducing the EN 12354-1 Annex H.3
(R'w = 52 dB) and Annex E.3 (L'n,w = 45 dB) worked examples. Add the matching
theory subsections, API-reference rows for every new public name, README and
landing-page entries (29 -> 33 standards), and CHANGELOG. EN docs and site
twins keep byte-identical code blocks.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: flanking-paths diagram, prediction and uncertainty figures
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de edificación II (fachadas, laboratorio, predicción, incertidumbre)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: PR-B final-review fixes — count, GitHub-safe math, edition alignment
Landing count corrected to 34 standards (slash-part convention); the
GitHub-unsafe math spacing tokens reintroduced by the new building
sections are scrubbed from the docs/ tree and its site twins; the whole
ISO 10140-2 citation chain aligned to the verified :2010 edition; plus
the six minor documentation-precision fixes from the final review.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 88 review round 1 — isfinite idiom, heading levels, frequencies validation
- building_prediction._check_finite: replace 'v != v or v in (inf,-inf)'
NaN idiom with math.isfinite for SonarCloud (same behavior, cleaner).
- room-acoustics docs (EN docs + site, ES site): relevel the three
parameter-table headings that skipped H2->H4 to H3 (MD001).
- insulation.facade_insulation: validate 'frequencies' length against the
band count, raising a clear ValueError instead of deferring a matplotlib
shape error to plot(). lab_insulation/building_uncertainty have no such
gap (no user-supplied frequencies stored). Regenerated llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Building acoustics II: facade insulation (ISO 16283-3), laboratory measurement (ISO 10140), prediction with flanking (EN 12354) and uncertainty (ISO 12999-1) (#88)
* feat: ISO 16283-3 facade sound insulation
Add facade_insulation() and FacadeInsulationResult for field facade sound
insulation per ISO 16283-3: the global-method level difference D2m and its
standardized (D2m,nT) and normalized (D2m,n) forms, plus the element-method
apparent sound reduction index R'45 (loudspeaker, -1,5 dB) / R'tr,s (road
traffic, -3 dB). Reuses the ISO 16283-1 energy-averaging helpers, the
Sabine absorption area, and the ISO 717-1 airborne weighted_rating engine
unchanged for the single-number rating. Adds a per-band .plot() profile and
exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 16283-3 draft-edition caveat and symmetric R' validation
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 10140 laboratory airborne and impact sound insulation
Add src/phonometry/lab_insulation.py, the laboratory counterpart of the
field ISO 16283 family:
- lab_airborne_insulation: R = L1 - L2 + 10 lg(S/A) with A = 0,16 V/T
(ISO 10140-2:2010 Formula (2); ISO 10140-4:2010 Formula (5)).
- lab_impact_insulation: Ln = Li + 10 lg(A/A0), A0 = 10 m²
(ISO 10140-3:2010 Formula (1)).
- background_correction: ISO 10140-4:2010 Clause 4.3 Formula (4) with the
6/15 dB criteria and the 1,3 dB limit-of-measurement cap.
Single-number Rw / Ln,w with C, Ctr, CI reuse the verified ISO 717-1/2
weighted_rating / weighted_impact_rating engines; position energy
averaging reuses _as_band_levels. 29 new closed-form / identity tests.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reconcile facade citations with published ISO 16283-3:2016
The facade module was drafted from ISO/DIS 16283-3:2014; its docstrings
cited draft formula numbers with a caveat to reconcile against the
published edition. Reconciled against ISO 16283-3:2016(E) (First edition
2016-02-01):
- Clause numbers are edition-stable: the field-quantity definitions keep
3.12 (R'45deg), 3.13 (R'tr,s), 3.14 (D2m), 3.15 (D2m,nT), 3.16 (D2m,n),
3.17 (A=0,16V/T), and 9.5.1 (surface-level averaging).
- Formula numbers differ: in the 2016 edition the Clause 3 defining
formulas are UNNUMBERED (inline in the term definitions); the numbered
formulas (1)-(21) live in the procedural clauses. The surface-level
energy-average is Formula (7) in 2016 (was Formula (20) in the DIS).
- Dropped the invalid draft Formula (2)-(7) citations from the field-
quantity docstrings and the draft-edition reconciliation caveat.
- Constants and formula bodies are unchanged (-1,5 dB / -3 dB, A0=10 m2,
T0=0,5 s, A=0,16V/T, band ranges): no numeric change; 22 facade tests
green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: EN 12354-1/2 building acoustic performance prediction with flanking
Implement the EN 12354:2000 simplified single-number prediction model for
apparent airborne (R'w) and impact (L'n,w) sound insulation, including direct
plus flanking transmission (Ff/Df/Fd paths) and the Annex E vibration-reduction
index Kij for rigid cross, rigid T, flexible-interlayer and lightweight-facade
junctions.
Airborne Formula (26)/(27)/(28a) with l0=1 m, Kij,min (29), lining composition
(30)/(31); impact Formula (21) with bare-floor Ln,w,eq (164-35 lg m'), Table 1
flanking correction K, and standardized L'nT,w (3). Results expose per-path
energy contributions so the dominant flanking path is visible.
Validated against the standards' worked examples: Part 1 Annex H.3 airborne
(R'w = 52 dB, 13 paths; +floating-floor 53 dB) and Part 2 Annex E.3 impact
(L'n,w = 45 dB, L'nT,w = 43 dB); all four Annex H junctions reproduce Kij.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 12999-1 building acoustics measurement uncertainty
Add building_uncertainty module implementing ISO 12999-1:2020 standard
uncertainties for sound-insulation quantities: per-band and single-number
values for airborne (Tables 2/3), impact (Tables 4/5) and floor-covering
reduction (Tables 6/7), across measurement situations A/B/C (Clause 5.2),
plus the Annex D sigma_R95 upper limits, Table 1 max repeatability and
Table 8 coverage factors.
Expansion U = k*u with k >= 1 (Clause 8), one-sided factors for conformity
checks (Formulae 4/5), and combination rules from Annexes A/B/C (prediction
input A.1, quadrature A.2/C.2, m-measurement reduction A.7, uncorrelated
single-number B.2). Composable UncertainValue attaches value +- U without
touching the rating dataclasses.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: numpy-stub-agnostic annotations for the two env-dependent mypy sites
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: PR-B review minors — anchors, Kij floor, uncertainty polish
- Table 3 r_w+ctr_50_5000 σsitu(B)=1.0 verified digit-by-digit against the
ISO 12999-1:2020(E) page image; anomalous but normative (comment added).
- Anchor the ISO 10140 rating tests to independent literals (Rw=54, Ln,w=58 —
reference-curve shape + the 32 dB / 16-band = 2 dB ISO 717 shift).
- background_correction: cross-ref sound_power.background_noise_correction and
document the negative-margin (Lb > Lsb) cap at Lsb−1.3.
- flanking_path: optional kij_min clamp for EN 12354-1 Clause 4.4.2 (Kij≥Kij,min),
documented on flanking_element; tested clamped vs unclamped (H.3 unaffected).
- impact_flanking_correction: comment on nearest-neighbour + tie-to-lower.
- Export COVERAGE_FACTORS (Table 8) as public API.
- single_number_uncertainty: note impact situation A is an estimate (Table 5 fn a).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: conformance checks for facade, lab insulation, EN 12354 and ISO 12999
Add six numerical conformance checks for the PR-B building-acoustics
standards, following the established registry pattern (single source of
truth in tests/reference_data.py, clause citations, honest tolerances):
- ISO 16283-3:2016 Clause 3.12: facade R'45 isolates the -1.5 dB
oblique-incidence correction on an S=A constructed case (exact).
- ISO 10140-2:2021 Formula (2): lab airborne R laid on the ISO 717-1
reference shape (S=A) -> Rw = 54 (the +2-shift analytic anchor).
- EN 12354-1:2000 Annex H.3: airborne prediction R'w = 52 from the 13
transmission paths (direct + 12 flanking), the branch's strongest oracle.
- EN 12354-2:2000 Annex E.3: impact prediction L'n,w = 45 (76-33+2).
- ISO 12999-1:2020 Table 2: airborne band uncertainty, situation A @
1 kHz = 1.8 dB (digit-exact), and Clause 8/Table 8 expanded
uncertainty U = 1.96 u = 2.352 dB (exact k=1.96 arithmetic).
Facade and lab checks join "Room & building acoustics"; the EN 12354 /
ISO 12999 checks form a new "Building prediction & uncertainty" domain.
Registry grows 26 -> 32 checks across 7 domains. Shared expected values
and the Annex H.3 input table move into reference_data.py so the report
and tests cannot drift; a consistency test pins them to the published
worked-example results. docs/CONFORMANCE.md regenerated via make conformance.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: building acoustics II — facade, laboratory, prediction and uncertainty (EN)
Extend the Room & Building Acoustics guide with facade insulation
(ISO 16283-3), laboratory characterisation (ISO 10140), flanking-transmission
performance prediction (EN 12354-1/2) and measurement uncertainty
(ISO 12999-1), with executed snippets reproducing the EN 12354-1 Annex H.3
(R'w = 52 dB) and Annex E.3 (L'n,w = 45 dB) worked examples. Add the matching
theory subsections, API-reference rows for every new public name, README and
landing-page entries (29 -> 33 standards), and CHANGELOG. EN docs and site
twins keep byte-identical code blocks.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: flanking-paths diagram, prediction and uncertainty figures
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de edificación II (fachadas, laboratorio, predicción, incertidumbre)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: PR-B final-review fixes — count, GitHub-safe math, edition alignment
Landing count corrected to 34 standards (slash-part convention); the
GitHub-unsafe math spacing tokens reintroduced by the new building
sections are scrubbed from the docs/ tree and its site twins; the whole
ISO 10140-2 citation chain aligned to the verified :2010 edition; plus
the six minor documentation-precision fixes from the final review.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 88 review round 1 — isfinite idiom, heading levels, frequencies validation
- building_prediction._check_finite: replace 'v != v or v in (inf,-inf)'
NaN idiom with math.isfinite for SonarCloud (same behavior, cleaner).
- room-acoustics docs (EN docs + site, ES site): relevel the three
parameter-table headings that skipped H2->H4 to H3 (MD001).
- insulation.facade_insulation: validate 'frequencies' length against the
band count, raising a clear ValueError instead of deferring a matplotlib
shape error to plot(). lab_insulation/building_uncertainty have no such
gap (no user-supplied frequencies stored). Regenerated llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Building acoustics II: facade insulation (ISO 16283-3), laboratory measurement (ISO 10140), prediction with flanking (EN 12354) and uncertainty (ISO 12999-1) (#88)
* feat: ISO 16283-3 facade sound insulation
Add facade_insulation() and FacadeInsulationResult for field facade sound
insulation per ISO 16283-3: the global-method level difference D2m and its
standardized (D2m,nT) and normalized (D2m,n) forms, plus the element-method
apparent sound reduction index R'45 (loudspeaker, -1,5 dB) / R'tr,s (road
traffic, -3 dB). Reuses the ISO 16283-1 energy-averaging helpers, the
Sabine absorption area, and the ISO 717-1 airborne weighted_rating engine
unchanged for the single-number rating. Adds a per-band .plot() profile and
exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 16283-3 draft-edition caveat and symmetric R' validation
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 10140 laboratory airborne and impact sound insulation
Add src/phonometry/lab_insulation.py, the laboratory counterpart of the
field ISO 16283 family:
- lab_airborne_insulation: R = L1 - L2 + 10 lg(S/A) with A = 0,16 V/T
(ISO 10140-2:2010 Formula (2); ISO 10140-4:2010 Formula (5)).
- lab_impact_insulation: Ln = Li + 10 lg(A/A0), A0 = 10 m²
(ISO 10140-3:2010 Formula (1)).
- background_correction: ISO 10140-4:2010 Clause 4.3 Formula (4) with the
6/15 dB criteria and the 1,3 dB limit-of-measurement cap.
Single-number Rw / Ln,w with C, Ctr, CI reuse the verified ISO 717-1/2
weighted_rating / weighted_impact_rating engines; position energy
averaging reuses _as_band_levels. 29 new closed-form / identity tests.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reconcile facade citations with published ISO 16283-3:2016
The facade module was drafted from ISO/DIS 16283-3:2014; its docstrings
cited draft formula numbers with a caveat to reconcile against the
published edition. Reconciled against ISO 16283-3:2016(E) (First edition
2016-02-01):
- Clause numbers are edition-stable: the field-quantity definitions keep
3.12 (R'45deg), 3.13 (R'tr,s), 3.14 (D2m), 3.15 (D2m,nT), 3.16 (D2m,n),
3.17 (A=0,16V/T), and 9.5.1 (surface-level averaging).
- Formula numbers differ: in the 2016 edition the Clause 3 defining
formulas are UNNUMBERED (inline in the term definitions); the numbered
formulas (1)-(21) live in the procedural clauses. The surface-level
energy-average is Formula (7) in 2016 (was Formula (20) in the DIS).
- Dropped the invalid draft Formula (2)-(7) citations from the field-
quantity docstrings and the draft-edition reconciliation caveat.
- Constants and formula bodies are unchanged (-1,5 dB / -3 dB, A0=10 m2,
T0=0,5 s, A=0,16V/T, band ranges): no numeric change; 22 facade tests
green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: EN 12354-1/2 building acoustic performance prediction with flanking
Implement the EN 12354:2000 simplified single-number prediction model for
apparent airborne (R'w) and impact (L'n,w) sound insulation, including direct
plus flanking transmission (Ff/Df/Fd paths) and the Annex E vibration-reduction
index Kij for rigid cross, rigid T, flexible-interlayer and lightweight-facade
junctions.
Airborne Formula (26)/(27)/(28a) with l0=1 m, Kij,min (29), lining composition
(30)/(31); impact Formula (21) with bare-floor Ln,w,eq (164-35 lg m'), Table 1
flanking correction K, and standardized L'nT,w (3). Results expose per-path
energy contributions so the dominant flanking path is visible.
Validated against the standards' worked examples: Part 1 Annex H.3 airborne
(R'w = 52 dB, 13 paths; +floating-floor 53 dB) and Part 2 Annex E.3 impact
(L'n,w = 45 dB, L'nT,w = 43 dB); all four Annex H junctions reproduce Kij.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 12999-1 building acoustics measurement uncertainty
Add building_uncertainty module implementing ISO 12999-1:2020 standard
uncertainties for sound-insulation quantities: per-band and single-number
values for airborne (Tables 2/3), impact (Tables 4/5) and floor-covering
reduction (Tables 6/7), across measurement situations A/B/C (Clause 5.2),
plus the Annex D sigma_R95 upper limits, Table 1 max repeatability and
Table 8 coverage factors.
Expansion U = k*u with k >= 1 (Clause 8), one-sided factors for conformity
checks (Formulae 4/5), and combination rules from Annexes A/B/C (prediction
input A.1, quadrature A.2/C.2, m-measurement reduction A.7, uncorrelated
single-number B.2). Composable UncertainValue attaches value +- U without
touching the rating dataclasses.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: numpy-stub-agnostic annotations for the two env-dependent mypy sites
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: PR-B review minors — anchors, Kij floor, uncertainty polish
- Table 3 r_w+ctr_50_5000 σsitu(B)=1.0 verified digit-by-digit against the
ISO 12999-1:2020(E) page image; anomalous but normative (comment added).
- Anchor the ISO 10140 rating tests to independent literals (Rw=54, Ln,w=58 —
reference-curve shape + the 32 dB / 16-band = 2 dB ISO 717 shift).
- background_correction: cross-ref sound_power.background_noise_correction and
document the negative-margin (Lb > Lsb) cap at Lsb−1.3.
- flanking_path: optional kij_min clamp for EN 12354-1 Clause 4.4.2 (Kij≥Kij,min),
documented on flanking_element; tested clamped vs unclamped (H.3 unaffected).
- impact_flanking_correction: comment on nearest-neighbour + tie-to-lower.
- Export COVERAGE_FACTORS (Table 8) as public API.
- single_number_uncertainty: note impact situation A is an estimate (Table 5 fn a).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: conformance checks for facade, lab insulation, EN 12354 and ISO 12999
Add six numerical conformance checks for the PR-B building-acoustics
standards, following the established registry pattern (single source of
truth in tests/reference_data.py, clause citations, honest tolerances):
- ISO 16283-3:2016 Clause 3.12: facade R'45 isolates the -1.5 dB
oblique-incidence correction on an S=A constructed case (exact).
- ISO 10140-2:2021 Formula (2): lab airborne R laid on the ISO 717-1
reference shape (S=A) -> Rw = 54 (the +2-shift analytic anchor).
- EN 12354-1:2000 Annex H.3: airborne prediction R'w = 52 from the 13
transmission paths (direct + 12 flanking), the branch's strongest oracle.
- EN 12354-2:2000 Annex E.3: impact prediction L'n,w = 45 (76-33+2).
- ISO 12999-1:2020 Table 2: airborne band uncertainty, situation A @
1 kHz = 1.8 dB (digit-exact), and Clause 8/Table 8 expanded
uncertainty U = 1.96 u = 2.352 dB (exact k=1.96 arithmetic).
Facade and lab checks join "Room & building acoustics"; the EN 12354 /
ISO 12999 checks form a new "Building prediction & uncertainty" domain.
Registry grows 26 -> 32 checks across 7 domains. Shared expected values
and the Annex H.3 input table move into reference_data.py so the report
and tests cannot drift; a consistency test pins them to the published
worked-example results. docs/CONFORMANCE.md regenerated via make conformance.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: building acoustics II — facade, laboratory, prediction and uncertainty (EN)
Extend the Room & Building Acoustics guide with facade insulation
(ISO 16283-3), laboratory characterisation (ISO 10140), flanking-transmission
performance prediction (EN 12354-1/2) and measurement uncertainty
(ISO 12999-1), with executed snippets reproducing the EN 12354-1 Annex H.3
(R'w = 52 dB) and Annex E.3 (L'n,w = 45 dB) worked examples. Add the matching
theory subsections, API-reference rows for every new public name, README and
landing-page entries (29 -> 33 standards), and CHANGELOG. EN docs and site
twins keep byte-identical code blocks.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: flanking-paths diagram, prediction and uncertainty figures
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de edificación II (fachadas, laboratorio, predicción, incertidumbre)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: PR-B final-review fixes — count, GitHub-safe math, edition alignment
Landing count corrected to 34 standards (slash-part convention); the
GitHub-unsafe math spacing tokens reintroduced by the new building
sections are scrubbed from the docs/ tree and its site twins; the whole
ISO 10140-2 citation chain aligned to the verified :2010 edition; plus
the six minor documentation-precision fixes from the final review.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 88 review round 1 — isfinite idiom, heading levels, frequencies validation
- building_prediction._check_finite: replace 'v != v or v in (inf,-inf)'
NaN idiom with math.isfinite for SonarCloud (same behavior, cleaner).
- room-acoustics docs (EN docs + site, ES site): relevel the three
parameter-table headings that skipped H2->H4 to H3 (MD001).
- insulation.facade_insulation: validate 'frequencies' length against the
band count, raising a clear ValueError instead of deferring a matplotlib
shape error to plot(). lab_insulation/building_uncertainty have no such
gap (no user-supplied frequencies stored). Regenerated llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Human vibration exposure (ISO 8041-1, ISO 2631, ISO 5349, Directive 2002/44/EC) (#94)
New `human_vibration` module implementing the ISO 8041-1:2017 master
weighting cascade (all nine weightings Wb/Wc/Wd/We/Wf/Wh/Wj/Wk/Wm),
ISO 2631-1/-2/-4 whole-body metrics (running RMS, MTVV, VDV, MSDV, crest
factor, vibration total value, energy-equivalent acceleration), the
ISO 5349-1/-2 hand-arm A(8) arithmetic and vibration-white-finger latency,
and the Directive 2002/44/EC EAV/ELV assessment. Every result object exposes
.plot(); validated to <0.05% against the ISO 8041-1 Annex B tables and the
ISO 5349-2 Annex E worked examples. Includes docs page, figures, setup
diagram, and 7 conformance checks (100%).
Human vibration exposure (ISO 8041-1, ISO 2631, ISO 5349, Directive 2002/44/EC) (#94)
New `human_vibration` module implementing the ISO 8041-1:2017 master
weighting cascade (all nine weightings Wb/Wc/Wd/We/Wf/Wh/Wj/Wk/Wm),
ISO 2631-1/-2/-4 whole-body metrics (running RMS, MTVV, VDV, MSDV, crest
factor, vibration total value, energy-equivalent acceleration), the
ISO 5349-1/-2 hand-arm A(8) arithmetic and vibration-white-finger latency,
and the Directive 2002/44/EC EAV/ELV assessment. Every result object exposes
.plot(); validated to <0.05% against the ISO 8041-1 Annex B tables and the
ISO 5349-2 Annex E worked examples. Includes docs page, figures, setup
diagram, and 7 conformance checks (100%).
Human vibration exposure (ISO 8041-1, ISO 2631, ISO 5349, Directive 2002/44/EC) (#94)
New `human_vibration` module implementing the ISO 8041-1:2017 master
weighting cascade (all nine weightings Wb/Wc/Wd/We/Wf/Wh/Wj/Wk/Wm),
ISO 2631-1/-2/-4 whole-body metrics (running RMS, MTVV, VDV, MSDV, crest
factor, vibration total value, energy-equivalent acceleration), the
ISO 5349-1/-2 hand-arm A(8) arithmetic and vibration-white-finger latency,
and the Directive 2002/44/EC EAV/ELV assessment. Every result object exposes
.plot(); validated to <0.05% against the ISO 8041-1 Annex B tables and the
ISO 5349-2 Annex E worked examples. Includes docs page, figures, setup
diagram, and 7 conformance checks (100%).
Human vibration exposure (ISO 8041-1, ISO 2631, ISO 5349, Directive 2002/44/EC) (#94)
New `human_vibration` module implementing the ISO 8041-1:2017 master
weighting cascade (all nine weightings Wb/Wc/Wd/We/Wf/Wh/Wj/Wk/Wm),
ISO 2631-1/-2/-4 whole-body metrics (running RMS, MTVV, VDV, MSDV, crest
factor, vibration total value, energy-equivalent acceleration), the
ISO 5349-1/-2 hand-arm A(8) arithmetic and vibration-white-finger latency,
and the Directive 2002/44/EC EAV/ELV assessment. Every result object exposes
.plot(); validated to <0.05% against the ISO 8041-1 Annex B tables and the
ISO 5349-2 Annex E worked examples. Includes docs page, figures, setup
diagram, and 7 conformance checks (100%).
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Acoustic materials: impedance tube, airflow resistance & sound-absorption rating (ISO 10534-1/-2, ASTM E2611, ISO 9053-1/-2, ISO 11654) (#91)
* feat: impedance tube, airflow resistance and ISO 11654 absorption rating
Clean-room from the standards (no third-party tool referenced):
- impedance_tube.py: ISO 10534-2 two-microphone transfer-function method
(reflection factor, surface impedance/admittance, absorption), ISO 10534-1
standing-wave-ratio method, and ASTM E2611 four-microphone transfer-matrix
method (wave decomposition, two-load/one-load T-matrix, transmission loss,
material wavenumber and characteristic impedance). Kelvin (ISO) vs Celsius
(ASTM) speed-of-sound helpers keep the two sign/unit conventions apart.
- airflow_resistance.py: ISO 9053-1 static method (through-origin quadratic
fit) and ISO 9053-2 alternating method (Formula 2), with R_s in Pa·s/m and
resistivity in Pa·s/m².
- absorption_rating.py: ISO 11654 weighted absorption alpha_w (0.05-grid
reference-curve shift, L/M/H shape indicators, absorption classes A-E),
verified against the Annex A.1/A.2 worked examples.
103 module tests plus public-export checks; physics-identity anchors for the
tube (rigid wall alpha=0, perfect absorber r=0/Z=rhoc, det(T)=1, air-layer
recovery to <1e-9) since neither tube standard prints a numeric example.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* feat: ISO 9053-2 Annex A kappa', materials docs, figures & conformance
Address per-module review of the impedance-tube / materials modules:
- ISO 9053-2:2020 Annex A (normative): implement the heat-conduction-corrected
effective ratio of specific heats kappa' (Formula (A.7)) and the thermal
boundary-layer thickness b (A.4/A.5) as effective_kappa() and
thermal_boundary_layer_thickness(). The Annex A.3 worked example is a
digit-exact oracle (b = 1.83e-3 m, kappa' = 1.370). Fix the misleading
_ADIABATIC_KAPPA citation: 1.4 is the uncorrected adiabatic fallback, not the
Annex A output.
- absorption_rating: delegate .plot() to _plotting.plot_weighted_absorption,
matching the repo idiom (reuses _unfavourable_mask / _new_axes).
- docs/materials.md: new guide covering ISO 11654, ISO 9053-1/-2 and
ISO 10534-1/-2 + ASTM E2611, with runnable examples and three figures
(EN/ES, light/dark). Linked from the docs index.
- Conformance report: five materials checks (ISO 11654 Annex A.1/A.2,
ISO 9053-2 Annex A.3 b + kappa', ISO 10534-1 SWR); shared oracles in
reference_data.py. 48/48 checks pass.
Impedance-tube module review returned Approved (no code changes needed;
the Eq (20) phase citation was verified correct against ISO 10534-1 p.5).
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* docs: experimental-setup diagrams for the materials methods
Add hand-drawn SVG setup diagrams (EN/ES, light/dark) for the new methods,
mirroring the didactic style of the room-acoustics / outdoor diagrams, and
embed them in docs/materials.md:
- Impedance tube (ISO 10534-2): loudspeaker, tube, two flush microphones at
spacing s and distance x1 from the specimen face, rigid backing, incident/
reflected plane waves and the Eq. (17)-(19) relations.
- Four-microphone transmission-loss tube (ASTM E2611): source, two upstream
and two downstream microphones, adjustable two-load termination, the A/B/C/D
travelling waves, and s1/s2/l1/l2/d labelled to match the library's
transfer_matrix_two_load / wave_decomposition parameters (l1, l2 measured
from the specimen front reference plane).
- Airflow resistance (ISO 9053-1/-2): the static rig (specimen, laminar flow
q_v, differential manometer Δp) and the alternating rig (piston 1-4 Hz,
cavity V, specimen/airtight termination, cavity level L_p).
Also apply the whole-branch review's two before-merge items:
- airflow_resistance.py: add the module-level __all__ it was missing.
- impedance_tube.face_quantities: add functional tests (progressive/backward
wave impedance = ±rho*c) so the exported ASTM Eq. (21) helper is covered.
SVG text() now XML-escapes &, < and > so labels may contain them literally.
Diagrams validated by subagent against the standards' figures and the
library's public-API variable names; the ASTM l2 origin was corrected from
the rear to the front specimen face to match the library convention.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: harden ISO 11654 input coercion (bot review)
_coerce now rejects multi-dimensional array input instead of silently
flattening it (CodeRabbit) and rejects non-finite values with a clear message
instead of a cryptic downstream integer-conversion error (Gemini). Adds tests
for both.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
* fix: flag ill-conditioned transfer-matrix solves (bot review)
transfer_matrix_two_load / transfer_matrix_one_load now emit an
ImpedanceTubeWarning when the solve denominator is near-singular relative to
its operands — two insufficiently-different loads (two-load) or a near-resonant
geometry (one-load) — instead of silently propagating inf/nan (CodeRabbit).
Adds tests for both the singular and the well-conditioned case.
Claude-Session: https://claude.ai/code/session_01JJLhQzF5hTdnEi3bfmqnqm
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Room and building acoustics: ISO 18233, ISO 3382-1/2/3, ISO 16283-1 + ISO 717-1 (#81)
* feat: ISO 18233 sweep/MLS impulse-response acquisition
Add src/phonometry/room_ir.py implementing the ISO 18233:2006
deterministic-excitation IR front end: exponential sine sweep with exact
analytic phase (Annex B), linear spectral-division deconvolution with a
Farina inverse-filter option for harmonic separation (B.5), and
maximum-length-sequence generation (LFSR, orders 2-20) with circular
cross-correlation recovery (Annex A).
Validated against closed forms: known IIR bandpass recovered within 0.1 dB
in band (sweep and MLS), ideal chain to a band-limited delta, +3 dB SNR per
sweep-duration doubling (B.6), and all MLS orders verified as true
maximum-length sequences (autocorrelation L / -1).
433 passed, 12 skipped; ruff, mypy --strict and bandit clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382 room acoustic parameters from impulse responses
Add src/phonometry/room_acoustics.py implementing ISO 3382-1:2009 and
ISO 3382-2:2008 analysis of measured impulse responses:
- decay_curve(): Schroeder backward integration of the squared IR
(5.3.3, Eq. 1) with background-noise truncation at the noise/slope
crossing and exponential tail compensation (Eq. 3), broadband or per
IEC 61260 fractional-octave band.
- room_parameters(): per-band EDT (0/-10 dB, A.2.2), T20 (-5/-25 dB)
and T30 (-5/-35 dB) by least-squares fits (ISO 3382-2 Annex C),
clarity C50/C80 (Eq. A.10), definition D50 (Eq. A.11) and centre
time Ts (Eq. A.13), octave bands 125 Hz-4 kHz by default with a
one-third-octave option and a broadband mode.
- Validity flags per the 5.3.3 dynamic-range criterion (noise at least
evaluation range + 15 dB below the IR maximum: 25/35/45 dB) plus the
Annex B curvature indicator C = 100*(T30/T20 - 1).
Tests validate against closed forms for exponential decays (EDT = T20 =
T30 = T within 1 %; C_te = 10*lg(exp(13.8155*te/T) - 1); D50 =
1 - exp(-0.6908/T); Ts = T/13.8155), the exact C50/D50 relation
(Eq. A.12), double-slope decays (EDT < T20 < T30) and noise-driven
validity-flag behaviour, with tolerances far below the Table A.1 JNDs.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* chore: move figure/diagram generators to scripts/
generate_graphs.py and generate_diagrams.py join benchmark_filters.py
and gen_llms.py in scripts/, where dev tooling already lives. Updated
the Makefile graphs target, the sys.path bootstrap in the graph guard
tests and in generate_graphs.py itself (src/ is now one level up), the
CONTRIBUTING instructions and the theme-images.css pointer. Verified:
module loads from the new location and regenerating the SVG diagrams
produces byte-identical output.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3382-3 open-plan office spatial metrics
Add open_plan_metrics() computing the ISO 3382-3:2012 single-number
quantities from a line of workstation measurements: spatial decay rate
D2,S and nominal speech level Lp,A,S,4m (Clause 6.2, Eq.5; 2-16 m
positions on a log-distance regression) and distraction/privacy
distances rD/rP (Clause 6.3; STI-vs-distance linear regression crossing
0,50 and 0,20). Returns a frozen OpenPlanResult; validates the minimum
of four positions (5.2.2) and equal array lengths.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-1 field insulation and ISO 717-1 weighted ratings
Add phonometry.insulation implementing field airborne sound insulation
(ISO 16283-1:2014) and single-number weighted ratings with C/Ctr
(ISO 717-1):
- airborne_insulation: per-band level difference D (Formula (1)),
standardized level difference DnT = D + 10 lg(T/T0) (Formula (2)) and
apparent sound reduction index R' = D + 10 lg(S/A), A = 0,16 V/T
(Formula (4)/(5)); energy-averages microphone positions (Formula (9)).
- weighted_rating: reference-curve shifting method (Clause 4.4, Table 3)
with the 32,0/10,0 dB unfavourable-deviation bound, plus C/Ctr from the
Table 4 spectra (Clause 4.5). Reference values, spectra and method are
identical in the 2013 and 2020 editions.
- energy_average_level: ISO 16283-1 Formula (9) helper.
Verified against the ISO 717-1 Annex C worked example (Rw(C;Ctr) =
30(-2;-3), unfavourable sum 31,8 dB) and exact-bound / tipping edge
cases. 20 new tests; make check green (484 passed, 12 skipped).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: room & building acoustics guide, theory, API and landing (EN)
New "Room & building acoustics" guide (docs/ + Starlight twin) covering the
full measurement chain: ISO 18233 swept-sine/MLS impulse-response acquisition,
ISO 3382-1/2 decay analysis and room parameters (EDT/T20/T30/C50/C80/D50/Ts),
ISO 3382-3 open-plan speech metrics, and ISO 16283-1 / ISO 717-1 field
insulation with weighted ratings. Adds the matching theory section (Schroeder
integration, regression windows, C/D/Ts, D2,S, DnT/R', reference-curve method),
API-reference rows for all new public names, sidebar entry, README highlight +
docs row, EN landing card, CHANGELOG entries, docs index row, and regenerated
llms-full.txt. All snippets validated; site build and make check green.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Schroeder, ISO 717-1 rating and insulation-setup figures
Add three room/building-acoustics documentation figure sets (each in
en/es x light/dark):
- schroeder_decay: synthetic IR, Schroeder backward integration with
EDT/T20/T30 regressions and evaluation ranges (ISO 3382); annotated
values match room_parameters.
- insulation_rating: ISO 717-1 Annex C example with shifted reference
curve, unfavourable-deviation shading and Rw read at 500 Hz; Rw, C,
Ctr and the unfavourable sum come from weighted_rating.
- diagram_insulation_setup: ISO 16283-1 airborne setup plan view with
the normative minimum distances (clauses 7.6 and 7.2.2).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de acústica de salas y edificación
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: terminología UNE — ponderación temporal en lugar de balística (ES)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: markdown/README parity with the site + llms guide coverage
Scrub GitHub-unsafe display math (\, thin-spaces and escaped \{ \}) from
docs/intensity.md and docs/psychoacoustics.md — the only two guides that
missed the GitHub-safe math conversion of PRs #78/#79 — matching the safe
forms already used in docs/theory.md. Align calibration's sensitivity
symbol/formula to the site ($S$, single-line \qquad).
Extend scripts/gen_llms.py PAGES with the three omitted guides
(psychoacoustics, intensity, room-acoustics) and regenerate llms.txt /
llms-full.txt so AI-facing artifacts cover all 14 docs pages.
The guides/references were otherwise already in parity (didactic code
comments, theory sections, tables, and figures from PRs #77/#80 all
present); docs/README index and README highlights/table verified complete.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — open_plan validation, limits rename, Farina caveat, MLS averaging test
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: ISO 18233 measurement-chain diagram and guide fixes
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: fix sweep_signal cross-reference in Farina caveat
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 81 review round 1 — inverse-filter guards, truncation threshold, IR input validation, docs pipeline wording
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: blank lines around CONTRIBUTING fence (MD031)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
ISO 2631-5: multiple-shock whole-body vibration (#106)
* feat: ISO 2631-5 multiple-shock whole-body vibration
Add the ISO 2631-5:2018 spinal-response model for whole-body vibration
containing multiple shocks: the normative Clause 5 dose and the Annex C
injury assessment (the vertical z-axis).
A seat-to-spine transfer function (clause 5.2, Formula 1) maps the
measured seat acceleration to the spinal response Az(t); the acceleration
dose Dz = 1.07*(sum Az,i^6)^(1/6) combines the positive response peaks
(Formula 3), scaled to a daily dose (Formula 4/5). Annex C turns the
daily dose into the compressive stress Sd = mz*Dzd (C.1), the
age-cumulated stress variable R (C.3/C.4) and the Weibull probability of
lumbar injury (C.5).
New module phonometry.iso2631_5 with seat_to_spine_transfer,
spinal_response, acceleration_dose, daily_dose(_multi), compression_dose,
injury_risk, injury_probability and the multiple_shock_assessment
convenience returning a MultipleShockResult with .plot(). Conformance
report gains a multiple-shock domain (3 checks, 88 total). Adds the
multiple-shock-vibration guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated against the standard: the seat-to-spine transfer function
reproduces the Annex D 256 Hz digital realization to within the clause
5.2 tolerance, and the Annex C worked example (5 x 40 m/s2, 82 kg male)
gives Dzd=55.97 m/s2, R=1.22 and injury probability 0.37.
* refactor: address review feedback on ISO 2631-5
- response_peaks: vectorize the positive-peak search with NumPy instead
of a Python loop (Gemini, CodeRabbit)
- injury_probability: accept array-like R and return an array or float,
clamping negative R to zero (Gemini)
- multiple_shock_assessment: raise if only one of exposure_time /
measurement_time is given instead of silently skipping the daily-dose
scaling (Gemini, CodeRabbit)
- spinal_response: reject multi-dimensional input with a clear error
(CodeRabbit)
- export static_stress alongside the other Annex C helpers (CodeRabbit)
- figure/plot: use the vectorized injury_probability directly
- tests: assert_allclose over the transfer-function band, use MZ_MALE
and strict zip, cover array probability and the partial-argument guard
- es guide: consistent decimal style in the code comment (CodeRabbit)
* fix: Spanish decimal comma in mathtext figure legends
The decimal-comma pass skips any label containing mathtext ($...$), so
the ISO 2631-5 'Ejemplo $R$ = 1.22' and NT ACOU 112 'Determinante
$K_I$ = 13.0 dB' legends kept a dot in Spanish. Fold the decimal
conversion into the _ES_PATTERNS rules for those labels (CodeRabbit).
ISO 2631-5: multiple-shock whole-body vibration (#106)
* feat: ISO 2631-5 multiple-shock whole-body vibration
Add the ISO 2631-5:2018 spinal-response model for whole-body vibration
containing multiple shocks: the normative Clause 5 dose and the Annex C
injury assessment (the vertical z-axis).
A seat-to-spine transfer function (clause 5.2, Formula 1) maps the
measured seat acceleration to the spinal response Az(t); the acceleration
dose Dz = 1.07*(sum Az,i^6)^(1/6) combines the positive response peaks
(Formula 3), scaled to a daily dose (Formula 4/5). Annex C turns the
daily dose into the compressive stress Sd = mz*Dzd (C.1), the
age-cumulated stress variable R (C.3/C.4) and the Weibull probability of
lumbar injury (C.5).
New module phonometry.iso2631_5 with seat_to_spine_transfer,
spinal_response, acceleration_dose, daily_dose(_multi), compression_dose,
injury_risk, injury_probability and the multiple_shock_assessment
convenience returning a MultipleShockResult with .plot(). Conformance
report gains a multiple-shock domain (3 checks, 88 total). Adds the
multiple-shock-vibration guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated against the standard: the seat-to-spine transfer function
reproduces the Annex D 256 Hz digital realization to within the clause
5.2 tolerance, and the Annex C worked example (5 x 40 m/s2, 82 kg male)
gives Dzd=55.97 m/s2, R=1.22 and injury probability 0.37.
* refactor: address review feedback on ISO 2631-5
- response_peaks: vectorize the positive-peak search with NumPy instead
of a Python loop (Gemini, CodeRabbit)
- injury_probability: accept array-like R and return an array or float,
clamping negative R to zero (Gemini)
- multiple_shock_assessment: raise if only one of exposure_time /
measurement_time is given instead of silently skipping the daily-dose
scaling (Gemini, CodeRabbit)
- spinal_response: reject multi-dimensional input with a clear error
(CodeRabbit)
- export static_stress alongside the other Annex C helpers (CodeRabbit)
- figure/plot: use the vectorized injury_probability directly
- tests: assert_allclose over the transfer-function band, use MZ_MALE
and strict zip, cover array probability and the partial-argument guard
- es guide: consistent decimal style in the code comment (CodeRabbit)
* fix: Spanish decimal comma in mathtext figure legends
The decimal-comma pass skips any label containing mathtext ($...$), so
the ISO 2631-5 'Ejemplo $R$ = 1.22' and NT ACOU 112 'Determinante
$K_I$ = 13.0 dB' legends kept a dot in Spanish. Fold the decimal
conversion into the _ES_PATTERNS rules for those labels (CodeRabbit).
ISO 2631-5: multiple-shock whole-body vibration (#106)
* feat: ISO 2631-5 multiple-shock whole-body vibration
Add the ISO 2631-5:2018 spinal-response model for whole-body vibration
containing multiple shocks: the normative Clause 5 dose and the Annex C
injury assessment (the vertical z-axis).
A seat-to-spine transfer function (clause 5.2, Formula 1) maps the
measured seat acceleration to the spinal response Az(t); the acceleration
dose Dz = 1.07*(sum Az,i^6)^(1/6) combines the positive response peaks
(Formula 3), scaled to a daily dose (Formula 4/5). Annex C turns the
daily dose into the compressive stress Sd = mz*Dzd (C.1), the
age-cumulated stress variable R (C.3/C.4) and the Weibull probability of
lumbar injury (C.5).
New module phonometry.iso2631_5 with seat_to_spine_transfer,
spinal_response, acceleration_dose, daily_dose(_multi), compression_dose,
injury_risk, injury_probability and the multiple_shock_assessment
convenience returning a MultipleShockResult with .plot(). Conformance
report gains a multiple-shock domain (3 checks, 88 total). Adds the
multiple-shock-vibration guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated against the standard: the seat-to-spine transfer function
reproduces the Annex D 256 Hz digital realization to within the clause
5.2 tolerance, and the Annex C worked example (5 x 40 m/s2, 82 kg male)
gives Dzd=55.97 m/s2, R=1.22 and injury probability 0.37.
* refactor: address review feedback on ISO 2631-5
- response_peaks: vectorize the positive-peak search with NumPy instead
of a Python loop (Gemini, CodeRabbit)
- injury_probability: accept array-like R and return an array or float,
clamping negative R to zero (Gemini)
- multiple_shock_assessment: raise if only one of exposure_time /
measurement_time is given instead of silently skipping the daily-dose
scaling (Gemini, CodeRabbit)
- spinal_response: reject multi-dimensional input with a clear error
(CodeRabbit)
- export static_stress alongside the other Annex C helpers (CodeRabbit)
- figure/plot: use the vectorized injury_probability directly
- tests: assert_allclose over the transfer-function band, use MZ_MALE
and strict zip, cover array probability and the partial-argument guard
- es guide: consistent decimal style in the code comment (CodeRabbit)
* fix: Spanish decimal comma in mathtext figure legends
The decimal-comma pass skips any label containing mathtext ($...$), so
the ISO 2631-5 'Ejemplo $R$ = 1.22' and NT ACOU 112 'Determinante
$K_I$ = 13.0 dB' legends kept a dot in Spanish. Fold the decimal
conversion into the _ES_PATTERNS rules for those labels (CodeRabbit).
ISO 2631-5: multiple-shock whole-body vibration (#106)
* feat: ISO 2631-5 multiple-shock whole-body vibration
Add the ISO 2631-5:2018 spinal-response model for whole-body vibration
containing multiple shocks: the normative Clause 5 dose and the Annex C
injury assessment (the vertical z-axis).
A seat-to-spine transfer function (clause 5.2, Formula 1) maps the
measured seat acceleration to the spinal response Az(t); the acceleration
dose Dz = 1.07*(sum Az,i^6)^(1/6) combines the positive response peaks
(Formula 3), scaled to a daily dose (Formula 4/5). Annex C turns the
daily dose into the compressive stress Sd = mz*Dzd (C.1), the
age-cumulated stress variable R (C.3/C.4) and the Weibull probability of
lumbar injury (C.5).
New module phonometry.iso2631_5 with seat_to_spine_transfer,
spinal_response, acceleration_dose, daily_dose(_multi), compression_dose,
injury_risk, injury_probability and the multiple_shock_assessment
convenience returning a MultipleShockResult with .plot(). Conformance
report gains a multiple-shock domain (3 checks, 88 total). Adds the
multiple-shock-vibration guide (repo + EN/ES site) with a figure and a
flow diagram.
Validated against the standard: the seat-to-spine transfer function
reproduces the Annex D 256 Hz digital realization to within the clause
5.2 tolerance, and the Annex C worked example (5 x 40 m/s2, 82 kg male)
gives Dzd=55.97 m/s2, R=1.22 and injury probability 0.37.
* refactor: address review feedback on ISO 2631-5
- response_peaks: vectorize the positive-peak search with NumPy instead
of a Python loop (Gemini, CodeRabbit)
- injury_probability: accept array-like R and return an array or float,
clamping negative R to zero (Gemini)
- multiple_shock_assessment: raise if only one of exposure_time /
measurement_time is given instead of silently skipping the daily-dose
scaling (Gemini, CodeRabbit)
- spinal_response: reject multi-dimensional input with a clear error
(CodeRabbit)
- export static_stress alongside the other Annex C helpers (CodeRabbit)
- figure/plot: use the vectorized injury_probability directly
- tests: assert_allclose over the transfer-function band, use MZ_MALE
and strict zip, cover array probability and the partial-argument guard
- es guide: consistent decimal style in the code comment (CodeRabbit)
* fix: Spanish decimal comma in mathtext figure legends
The decimal-comma pass skips any label containing mathtext ($...$), so
the ISO 2631-5 'Ejemplo $R$ = 1.22' and NT ACOU 112 'Determinante
$K_I$ = 13.0 dB' legends kept a dot in Spanish. Fold the decimal
conversion into the _ES_PATTERNS rules for those labels (CodeRabbit).
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
feat: noise-induced hearing loss (ISO 1999:2013 NIPTS and HTLAN) (#103)
Adds a `phonometry.iso1999` module estimating occupational noise-induced hearing loss, extending the ISO 7029 age-related threshold with a noise component.
* `nipts(l_ex, years, fractile)` — noise-induced permanent threshold shift over 500-6000 Hz: median N50 (clause 6.3.1, Formula 2/3, Table 1) and population fractiles from the half-Gaussian spreads du/dl (clause 6.3.2, Formulae 4-7, Tables 2-3), clamped at zero.
* `htlan(age, sex, l_ex, years, fractile)` — hearing threshold level associated with age and noise, combining the age component (HTLA = ISO 7029) with the NIPTS by H' = H + N - H*N/120 (clause 6.1, Formula 1).
Validated against ISO 1999 Annex D (Tables D.1-D.4, 85-100 dB, 10-40 years): reproduces every tabulated dB value. Conformance 82/82; full suite 1686 passed. Figure + two-lane NIHL diagram (EN/ES, light/dark), repo doc and EN/ES site guides.
feat: noise-induced hearing loss (ISO 1999:2013 NIPTS and HTLAN) (#103)
Adds a `phonometry.iso1999` module estimating occupational noise-induced hearing loss, extending the ISO 7029 age-related threshold with a noise component.
* `nipts(l_ex, years, fractile)` — noise-induced permanent threshold shift over 500-6000 Hz: median N50 (clause 6.3.1, Formula 2/3, Table 1) and population fractiles from the half-Gaussian spreads du/dl (clause 6.3.2, Formulae 4-7, Tables 2-3), clamped at zero.
* `htlan(age, sex, l_ex, years, fractile)` — hearing threshold level associated with age and noise, combining the age component (HTLA = ISO 7029) with the NIPTS by H' = H + N - H*N/120 (clause 6.1, Formula 1).
Validated against ISO 1999 Annex D (Tables D.1-D.4, 85-100 dB, 10-40 years): reproduces every tabulated dB value. Conformance 82/82; full suite 1686 passed. Figure + two-lane NIHL diagram (EN/ES, light/dark), repo doc and EN/ES site guides.
feat: noise-induced hearing loss (ISO 1999:2013 NIPTS and HTLAN) (#103)
Adds a `phonometry.iso1999` module estimating occupational noise-induced hearing loss, extending the ISO 7029 age-related threshold with a noise component.
* `nipts(l_ex, years, fractile)` — noise-induced permanent threshold shift over 500-6000 Hz: median N50 (clause 6.3.1, Formula 2/3, Table 1) and population fractiles from the half-Gaussian spreads du/dl (clause 6.3.2, Formulae 4-7, Tables 2-3), clamped at zero.
* `htlan(age, sex, l_ex, years, fractile)` — hearing threshold level associated with age and noise, combining the age component (HTLA = ISO 7029) with the NIPTS by H' = H + N - H*N/120 (clause 6.1, Formula 1).
Validated against ISO 1999 Annex D (Tables D.1-D.4, 85-100 dB, 10-40 years): reproduces every tabulated dB value. Conformance 82/82; full suite 1686 passed. Figure + two-lane NIHL diagram (EN/ES, light/dark), repo doc and EN/ES site guides.
feat: noise-induced hearing loss (ISO 1999:2013 NIPTS and HTLAN) (#103)
Adds a `phonometry.iso1999` module estimating occupational noise-induced hearing loss, extending the ISO 7029 age-related threshold with a noise component.
* `nipts(l_ex, years, fractile)` — noise-induced permanent threshold shift over 500-6000 Hz: median N50 (clause 6.3.1, Formula 2/3, Table 1) and population fractiles from the half-Gaussian spreads du/dl (clause 6.3.2, Formulae 4-7, Tables 2-3), clamped at zero.
* `htlan(age, sex, l_ex, years, fractile)` — hearing threshold level associated with age and noise, combining the age component (HTLA = ISO 7029) with the NIPTS by H' = H + N - H*N/120 (clause 6.1, Formula 1).
Validated against ISO 1999 Annex D (Tables D.1-D.4, 85-100 dB, 10-40 years): reproduces every tabulated dB value. Conformance 82/82; full suite 1686 passed. Figure + two-lane NIHL diagram (EN/ES, light/dark), repo doc and EN/ES site guides.
NT ACOU 112: impulsive-sound prominence and LAeq adjustment (#105)
* feat: NT ACOU 112 impulsive-sound prominence and LAeq adjustment
Add the Nordtest NT ACOU 112:2002 method for the prominence of
impulsive sounds: the predicted prominence P = 3 lg(OR) + 2 lg(LD)
from each impulse's onset rate and level difference (clause 7,
Formula 1), the graduated adjustment KI = 1.8 (P - 5) dB for P > 5
(clause 8, Formula 2), and the rating level over a reference time
interval (clause 8, Note 1).
New module phonometry.ntacou112 with predicted_prominence,
impulse_adjustment, impulse_prominence (ImpulseProminence result with
.plot()) and rating_level. Conformance report gains an impulsive-sound
domain (2 checks). Adds the impulse-prominence guide (repo + EN/ES
site) with figure and flow diagram.
* refactor: address review feedback on NT ACOU 112
- impulse_prominence: ravel inputs so multi-dimensional arrays flatten
to a 1-D impulse sequence (Gemini)
- figure: use a distinct neutral for the threshold line instead of the
grid color, matching plot_impulse_prominence (Gemini)
- tests: use the shared NTACOU_PROMINENCE / NTACOU_ADJUSTMENT_P10
reference constants instead of hardcoded literals (CodeRabbit)
* refactor: second-pass review polish for NT ACOU 112
- figure: give the impulse markers a distinct light blue (#aec7e8),
matching plot_impulse_prominence, so they read apart from the neutral
threshold line (CodeRabbit)
- tests: split the chained magnitude/approx assertion into two clearer
assertions (CodeRabbit)
NT ACOU 112: impulsive-sound prominence and LAeq adjustment (#105)
* feat: NT ACOU 112 impulsive-sound prominence and LAeq adjustment
Add the Nordtest NT ACOU 112:2002 method for the prominence of
impulsive sounds: the predicted prominence P = 3 lg(OR) + 2 lg(LD)
from each impulse's onset rate and level difference (clause 7,
Formula 1), the graduated adjustment KI = 1.8 (P - 5) dB for P > 5
(clause 8, Formula 2), and the rating level over a reference time
interval (clause 8, Note 1).
New module phonometry.ntacou112 with predicted_prominence,
impulse_adjustment, impulse_prominence (ImpulseProminence result with
.plot()) and rating_level. Conformance report gains an impulsive-sound
domain (2 checks). Adds the impulse-prominence guide (repo + EN/ES
site) with figure and flow diagram.
* refactor: address review feedback on NT ACOU 112
- impulse_prominence: ravel inputs so multi-dimensional arrays flatten
to a 1-D impulse sequence (Gemini)
- figure: use a distinct neutral for the threshold line instead of the
grid color, matching plot_impulse_prominence (Gemini)
- tests: use the shared NTACOU_PROMINENCE / NTACOU_ADJUSTMENT_P10
reference constants instead of hardcoded literals (CodeRabbit)
* refactor: second-pass review polish for NT ACOU 112
- figure: give the impulse markers a distinct light blue (#aec7e8),
matching plot_impulse_prominence, so they read apart from the neutral
threshold line (CodeRabbit)
- tests: split the chained magnitude/approx assertion into two clearer
assertions (CodeRabbit)
Audit pass 7: bilingual EN/ES consistency (#116)
* docs: bilingual EN/ES consistency batch
Audit batch 7 - the Spanish side catches up with the English one:
Content drift: the five per-architecture filter figures join the ES
filter-banks guide; the missing outdoor-propagation card joins the ES
index (7 cards on both sides); the sound-power card says five methods
in both languages (it said three since before ISO 3745/9614-3).
Decimals: the four prose dot-decimals and four code-comment
comma-decimals fixed per convention, and the systematic LaTeX {,}
migration lands - 146 conversions across 16 ES files, every hit
manually reviewed (clause numbers, standard designations, def.:
literals and code identifiers deliberately untouched; zero \d.\d
remain in ES math). The theory band-edge table keeps points (it
mirrors a code snippet's printed output); the why-phonometry report
tables convert to commas (prose).
Terminology unified: fonios, diezmado (including the divergent
multirate alt pair), umbral de audicion, banda atenuada, nivel de
evaluacion (including the rendered NT ACOU 112 ES diagram - the
generator string is fixed and only that SVG pair regenerated),
sharpness (agudeza), and clausula/apartado unified per file majority
(theory: clausula; api: apartado).
Code comments: 22 English comments translated across gum-uncertainty,
hearing-threshold, noise-induced-hearing-loss, room-noise and
occupational-exposure ES (the occupational f-string outputs were
re-executed and match the echoed comments byte-for-byte).
* docs: 'atenuación en banda atenuada' in the ES filter guide
The glossary fix produced a clumsy repetition ('atenuación de banda
atenuada'); the natural phrasing for stopband attenuation is 'en'
(Copilot).
* docs: the sound-power cards enumerate the guide's five routes exactly
The card grouped ISO 9614-2/3 into one item, making 'five routes' read
as four groups (or six standards); it now mirrors the guide's canonical
five-item enumeration, in both languages (CodeRabbit).
Audit pass 7: bilingual EN/ES consistency (#116)
* docs: bilingual EN/ES consistency batch
Audit batch 7 - the Spanish side catches up with the English one:
Content drift: the five per-architecture filter figures join the ES
filter-banks guide; the missing outdoor-propagation card joins the ES
index (7 cards on both sides); the sound-power card says five methods
in both languages (it said three since before ISO 3745/9614-3).
Decimals: the four prose dot-decimals and four code-comment
comma-decimals fixed per convention, and the systematic LaTeX {,}
migration lands - 146 conversions across 16 ES files, every hit
manually reviewed (clause numbers, standard designations, def.:
literals and code identifiers deliberately untouched; zero \d.\d
remain in ES math). The theory band-edge table keeps points (it
mirrors a code snippet's printed output); the why-phonometry report
tables convert to commas (prose).
Terminology unified: fonios, diezmado (including the divergent
multirate alt pair), umbral de audicion, banda atenuada, nivel de
evaluacion (including the rendered NT ACOU 112 ES diagram - the
generator string is fixed and only that SVG pair regenerated),
sharpness (agudeza), and clausula/apartado unified per file majority
(theory: clausula; api: apartado).
Code comments: 22 English comments translated across gum-uncertainty,
hearing-threshold, noise-induced-hearing-loss, room-noise and
occupational-exposure ES (the occupational f-string outputs were
re-executed and match the echoed comments byte-for-byte).
* docs: 'atenuación en banda atenuada' in the ES filter guide
The glossary fix produced a clumsy repetition ('atenuación de banda
atenuada'); the natural phrasing for stopband attenuation is 'en'
(Copilot).
* docs: the sound-power cards enumerate the guide's five routes exactly
The card grouped ISO 9614-2/3 into one item, making 'five routes' read
as four groups (or six standards); it now mirrors the guide's canonical
five-item enumeration, in both languages (CodeRabbit).
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Outdoor sound propagation and occupational noise exposure (ISO 9613-1, ISO 9613-2, ISO 9612) (#89)
* feat: ISO 9613-1 atmospheric sound absorption
Full alpha(f, T, RH, p) model per ISO 9613-1:1993 clauses 6.2-6.4:
oxygen/nitrogen relaxation frequencies, water-vapour molar
concentration from relative humidity, classical + rotational +
vibrational terms. Validated against a 13-point Table 1 grid
(worst deviation 0.39 %, rounding-limited, vs the standard's
stated +/-10 % accuracy) with the exact midband convention of
Eq. (6) Note 5. air_attenuation_m() feeds the ISO 354 m parameter
directly, closing the user-supplied gap. Two conformance checks
added (34/34).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: C1 review nits — test name and comment direction
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: extend ISO 9613-1 Table 1 oracle against the full standard text
The full 37-page ISO 9613-1:1993 text (now in hand) confirms every
implemented constant of Eqs. (3)-(6), the Annex B psychrometric
conversion and the clause 4.2 reference conditions exactly as coded.
Oracle extended from 13 to 23 Table 1 points, adding the 20-50 degC
sub-tables 1(i)-1(p) unavailable in the interim source. Worst
deviation unchanged at 0.385 % (rounding-limited).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9613-2 outdoor sound propagation
Implement the ISO 9613-2:1996 general method for octave-band outdoor sound
attenuation: geometrical divergence (Eq. 7), atmospheric absorption (Eq. 8,
via ISO 9613-1 air_absorption), ground effect (general per-region method of
7.3.1 with the Table 3 a'/b'/c'/d' functions, Eq. 9, plus the alternative
method of 7.3.2, Eq. 10, and the DOmega index Eq. 11), and screening (Eq. 12-18
with the C2/C3 factors, single/double diffraction, Kmet and the 20/25 dB caps).
Adds the Cmet meteorological correction (Eq. 21/22) and the LfT(DW)=Lw+Dc-A
receiver-level composition (Eq. 3/6). Frozen dataclass result exposes the
per-term breakdown (Adiv/Aatm/Agr/Abar). New module, tests and exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9612 occupational noise exposure strategies and uncertainty
Add phonometry.occupational_exposure implementing the three ISO 9612:2009
measurement strategies and the normative Annex C uncertainty budget:
- task_based_exposure (Clause 9): per-task energy average (Eq 7), task
contributions (Eq 8), daily level (Eq 9/10); uncertainty Eq C.3 with
sampling u1a (Eq C.6), duration u1b (Eq C.7) and sensitivity coefficients
c1a (Eq C.4) / c1b (Eq C.5).
- job_based_exposure (Clause 10): effective-day energy average (Eq 11),
daily level (Eq 12); Table 1 minimum-duration check; uncertainty Eq C.9.
- full_day_exposure (Clause 11): whole-day averaging (Eq 11/13) with the
Clause 11.3 three-measurement / 3 dB spread rule.
- Table C.4 (job/full-day c1*u1, bilinear interpolation), Table C.5 (u2),
u3 = 1.0 dB, coverage factor k = 1.65 (one-sided 95 %).
Frozen dataclasses (Task, TaskContribution, ExposureResult), ExposureWarning
advisories for the sampling rules, and exports appended to __init__.
Tests reproduce the Annex D (task), E (job) and F (full-day) worked examples
to the standard's precision, plus closed-form oracles (single 85 dB/8 h task
= 85; equal-level tasks; -3.01 dB per halved duration; k = 1.65) and the
Table C.4 / Table 1 lookups. make check green: 1167 passed, 12 skipped.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 9612 review corrections — Table C.4 digits and Eq C.7 denominator
Two Table C.4 cells verified against the page image at 200 dpi and
corrected (N=6/u1=3.5: 3.4 -> 3.3; N=20/u1=2.0: 0.6 -> 0.5), the test
that echoed the wrong N=6 cell now pins the printed value plus the
corrected N=20 cell. The duration_samples branch of Eq C.7 divides by
J(J-1) like Eq C.6 (standard error of the mean), with a regression test
pinning u1b = 1.0 h for samples (4, 6) h. Module docstring now states
the Lp,Cpeak uncertainty scope cut (Table C.5, NOTE 1).
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* test: ISO 9613-2 and ISO 9612 conformance checks
Add a new "Outdoor propagation & occupational exposure" conformance domain
with seven closed-form / worked-example checks backed by shared constants in
tests/reference_data.py:
- ISO 9613-2:1996 Eq. (7) geometrical divergence Adiv = 51 dB at 100 m.
- ISO 9613-2:1996 Table 3 ground limit b'(0) = 10,1 -> Agr(250 Hz) = 17,2 dB
(porous ground, hs = hr = 0, dp -> inf).
- ISO 9613-2:1996 clause 7.4 single/double diffraction 20/25 dB caps.
- ISO 9612:2009 Annex D/E/F daily exposure LEX,8h and expanded uncertainty U
(84,3/2,7, 88,1/3,8, 90,1/3,4 dB), the Task objects rebuilt from the shared
input table.
Registry grows 34 -> 41 checks across 8 domains; docs/CONFORMANCE.md
regenerated via make conformance. Registration and reference-data consistency
tests pin the constants to the published values.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: figures for outdoor propagation and occupational exposure
Add four documentation figures (each EN/ES x light/dark) plus a setup diagram:
- air_absorption_alpha: ISO 9613-1 alpha(f) over frequency at four
temperature/humidity combinations (relaxation roll-off, f^2 growth).
- outdoor_attenuation_breakdown: ISO 9613-2 per-term stacked bar (Adiv, Aatm,
Agr, Abar) with the total A, for a 200 m path over porous ground with a 4 m
barrier.
- exposure_uncertainty: ISO 9612 Annex D task contributions with the daily
LEX,8h and the one-sided 95 % upper limit LEX,8h + U.
- diagram_outdoor_geometry: source-barrier-receiver geometry (dss/dsr/z, the
blocked direct ray and the diffracted ray over the top edge).
Spanish translations added to the generate_graphs / generate_diagrams
dictionaries (decimal commas, UNE terminology). Every image visually audited.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: ISO 9613-1/2 outdoor propagation guide and ISO 9612 exposure (EN)
Add the didactic Outdoor Sound Propagation guide (docs/outdoor-propagation.md)
covering ISO 9613-1 atmospheric absorption and the ISO 9613-2 general method
(divergence, atmospheric, ground and barrier terms, the OutdoorAttenuation
breakdown, the alternative 7.3.2 ground method, Cmet), with executed snippets
and honest scope notes (Amisc/reflections not implemented, 7.3.2 not
auto-wired, per-band Cmet a convenience). Extend the Levels guide with the
ISO 9612 occupational-exposure section (task/job/full-day strategies, the
C.6 I(I-1) vs C.12 N-1 asymmetry, Table C.4, k = 1,65, LEX,8h + U upper limit,
Lp,Cpeak uncertainty out of scope), reproducing the Annex D/E/F worked
examples.
Add the matching theory sections, API-reference rows for every new public
name, README feature list + docs table, docs index and CHANGELOG entries.
llms-full.txt / llms.txt regenerated (make llms) with the new page wired into
gen_llms.py. GitHub-safe math throughout; every snippet executed with pasted
outputs.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: outdoor propagation and exposure site twins (EN + ES)
Add the English and Spanish Starlight twins of the new content:
- guides/outdoor-propagation.md (EN + ES) — code-identical snippets to the
docs page; Spanish prose uses UNE terminology ("ponderación temporal"),
decimal commas outside math and code, and the _es figure variants.
- The ISO 9612 section added to guides/levels.md (EN + ES).
- reference/theory.md and reference/api.md rows (EN + ES).
- Landing cards and standards list bumped 34 -> 37 (index.mdx EN + ES);
guides/outdoor-propagation added to the sidebar.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: final branch review — API rows, precision phrasing and ES links
Adds the five missing public-symbol rows (TaskContribution,
table_c4_contribution, minimum_cumulative_duration_hours, COVERAGE_FACTOR,
INSTRUMENT_U2) to the three API references, states the ISO 9613-2 default
atmosphere (20 °C / 70 %, a Table 2 reference atmosphere) in the API rows
and guides, and softens "digit-for-digit" to "the standard's printed
precision" wherever it covered Annex E, whose final level differs only by
the standard's own pre-rounding. ES pages now use the /es/ link prefix
consistently. Code nits from the review: dead arg > 1 guard removed
(z > 0 implies arg >= 3), _with_advisory uses dataclasses.replace, and the
float-keyed _PRIME_BY_BAND gets a safety comment. llms files regenerated.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: validate propagation/exposure inputs and docs lint (PR review)
Addresses the PR #89 bot review:
- Barrier.__post_init__ rejects negative edge distances and a zero
edge_separation (which previously divided by zero in the C3 double-
diffraction factor); Task.__post_init__ rejects empty samples and a
non-positive duration.
- ground_attenuation and barrier_attenuation reject non-positive
frequencies (a zero frequency gave an infinite wavelength / division by
zero); ground_attenuation also checks a positive distance and
non-negative heights. job_based_exposure rejects a non-positive
sample_duration_hours.
- Rewrite the ISO 9613-2 7.3.2 closed form in the guides and API tables so
Markdownlint no longer parses `(...)[...]` as a reversed link (MD011).
- Regression tests for every new guard; docstrings note the new raises.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
Outdoor sound propagation and occupational noise exposure (ISO 9613-1, ISO 9613-2, ISO 9612) (#89)
* feat: ISO 9613-1 atmospheric sound absorption
Full alpha(f, T, RH, p) model per ISO 9613-1:1993 clauses 6.2-6.4:
oxygen/nitrogen relaxation frequencies, water-vapour molar
concentration from relative humidity, classical + rotational +
vibrational terms. Validated against a 13-point Table 1 grid
(worst deviation 0.39 %, rounding-limited, vs the standard's
stated +/-10 % accuracy) with the exact midband convention of
Eq. (6) Note 5. air_attenuation_m() feeds the ISO 354 m parameter
directly, closing the user-supplied gap. Two conformance checks
added (34/34).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: C1 review nits — test name and comment direction
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: extend ISO 9613-1 Table 1 oracle against the full standard text
The full 37-page ISO 9613-1:1993 text (now in hand) confirms every
implemented constant of Eqs. (3)-(6), the Annex B psychrometric
conversion and the clause 4.2 reference conditions exactly as coded.
Oracle extended from 13 to 23 Table 1 points, adding the 20-50 degC
sub-tables 1(i)-1(p) unavailable in the interim source. Worst
deviation unchanged at 0.385 % (rounding-limited).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9613-2 outdoor sound propagation
Implement the ISO 9613-2:1996 general method for octave-band outdoor sound
attenuation: geometrical divergence (Eq. 7), atmospheric absorption (Eq. 8,
via ISO 9613-1 air_absorption), ground effect (general per-region method of
7.3.1 with the Table 3 a'/b'/c'/d' functions, Eq. 9, plus the alternative
method of 7.3.2, Eq. 10, and the DOmega index Eq. 11), and screening (Eq. 12-18
with the C2/C3 factors, single/double diffraction, Kmet and the 20/25 dB caps).
Adds the Cmet meteorological correction (Eq. 21/22) and the LfT(DW)=Lw+Dc-A
receiver-level composition (Eq. 3/6). Frozen dataclass result exposes the
per-term breakdown (Adiv/Aatm/Agr/Abar). New module, tests and exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9612 occupational noise exposure strategies and uncertainty
Add phonometry.occupational_exposure implementing the three ISO 9612:2009
measurement strategies and the normative Annex C uncertainty budget:
- task_based_exposure (Clause 9): per-task energy average (Eq 7), task
contributions (Eq 8), daily level (Eq 9/10); uncertainty Eq C.3 with
sampling u1a (Eq C.6), duration u1b (Eq C.7) and sensitivity coefficients
c1a (Eq C.4) / c1b (Eq C.5).
- job_based_exposure (Clause 10): effective-day energy average (Eq 11),
daily level (Eq 12); Table 1 minimum-duration check; uncertainty Eq C.9.
- full_day_exposure (Clause 11): whole-day averaging (Eq 11/13) with the
Clause 11.3 three-measurement / 3 dB spread rule.
- Table C.4 (job/full-day c1*u1, bilinear interpolation), Table C.5 (u2),
u3 = 1.0 dB, coverage factor k = 1.65 (one-sided 95 %).
Frozen dataclasses (Task, TaskContribution, ExposureResult), ExposureWarning
advisories for the sampling rules, and exports appended to __init__.
Tests reproduce the Annex D (task), E (job) and F (full-day) worked examples
to the standard's precision, plus closed-form oracles (single 85 dB/8 h task
= 85; equal-level tasks; -3.01 dB per halved duration; k = 1.65) and the
Table C.4 / Table 1 lookups. make check green: 1167 passed, 12 skipped.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 9612 review corrections — Table C.4 digits and Eq C.7 denominator
Two Table C.4 cells verified against the page image at 200 dpi and
corrected (N=6/u1=3.5: 3.4 -> 3.3; N=20/u1=2.0: 0.6 -> 0.5), the test
that echoed the wrong N=6 cell now pins the printed value plus the
corrected N=20 cell. The duration_samples branch of Eq C.7 divides by
J(J-1) like Eq C.6 (standard error of the mean), with a regression test
pinning u1b = 1.0 h for samples (4, 6) h. Module docstring now states
the Lp,Cpeak uncertainty scope cut (Table C.5, NOTE 1).
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* test: ISO 9613-2 and ISO 9612 conformance checks
Add a new "Outdoor propagation & occupational exposure" conformance domain
with seven closed-form / worked-example checks backed by shared constants in
tests/reference_data.py:
- ISO 9613-2:1996 Eq. (7) geometrical divergence Adiv = 51 dB at 100 m.
- ISO 9613-2:1996 Table 3 ground limit b'(0) = 10,1 -> Agr(250 Hz) = 17,2 dB
(porous ground, hs = hr = 0, dp -> inf).
- ISO 9613-2:1996 clause 7.4 single/double diffraction 20/25 dB caps.
- ISO 9612:2009 Annex D/E/F daily exposure LEX,8h and expanded uncertainty U
(84,3/2,7, 88,1/3,8, 90,1/3,4 dB), the Task objects rebuilt from the shared
input table.
Registry grows 34 -> 41 checks across 8 domains; docs/CONFORMANCE.md
regenerated via make conformance. Registration and reference-data consistency
tests pin the constants to the published values.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: figures for outdoor propagation and occupational exposure
Add four documentation figures (each EN/ES x light/dark) plus a setup diagram:
- air_absorption_alpha: ISO 9613-1 alpha(f) over frequency at four
temperature/humidity combinations (relaxation roll-off, f^2 growth).
- outdoor_attenuation_breakdown: ISO 9613-2 per-term stacked bar (Adiv, Aatm,
Agr, Abar) with the total A, for a 200 m path over porous ground with a 4 m
barrier.
- exposure_uncertainty: ISO 9612 Annex D task contributions with the daily
LEX,8h and the one-sided 95 % upper limit LEX,8h + U.
- diagram_outdoor_geometry: source-barrier-receiver geometry (dss/dsr/z, the
blocked direct ray and the diffracted ray over the top edge).
Spanish translations added to the generate_graphs / generate_diagrams
dictionaries (decimal commas, UNE terminology). Every image visually audited.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: ISO 9613-1/2 outdoor propagation guide and ISO 9612 exposure (EN)
Add the didactic Outdoor Sound Propagation guide (docs/outdoor-propagation.md)
covering ISO 9613-1 atmospheric absorption and the ISO 9613-2 general method
(divergence, atmospheric, ground and barrier terms, the OutdoorAttenuation
breakdown, the alternative 7.3.2 ground method, Cmet), with executed snippets
and honest scope notes (Amisc/reflections not implemented, 7.3.2 not
auto-wired, per-band Cmet a convenience). Extend the Levels guide with the
ISO 9612 occupational-exposure section (task/job/full-day strategies, the
C.6 I(I-1) vs C.12 N-1 asymmetry, Table C.4, k = 1,65, LEX,8h + U upper limit,
Lp,Cpeak uncertainty out of scope), reproducing the Annex D/E/F worked
examples.
Add the matching theory sections, API-reference rows for every new public
name, README feature list + docs table, docs index and CHANGELOG entries.
llms-full.txt / llms.txt regenerated (make llms) with the new page wired into
gen_llms.py. GitHub-safe math throughout; every snippet executed with pasted
outputs.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: outdoor propagation and exposure site twins (EN + ES)
Add the English and Spanish Starlight twins of the new content:
- guides/outdoor-propagation.md (EN + ES) — code-identical snippets to the
docs page; Spanish prose uses UNE terminology ("ponderación temporal"),
decimal commas outside math and code, and the _es figure variants.
- The ISO 9612 section added to guides/levels.md (EN + ES).
- reference/theory.md and reference/api.md rows (EN + ES).
- Landing cards and standards list bumped 34 -> 37 (index.mdx EN + ES);
guides/outdoor-propagation added to the sidebar.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: final branch review — API rows, precision phrasing and ES links
Adds the five missing public-symbol rows (TaskContribution,
table_c4_contribution, minimum_cumulative_duration_hours, COVERAGE_FACTOR,
INSTRUMENT_U2) to the three API references, states the ISO 9613-2 default
atmosphere (20 °C / 70 %, a Table 2 reference atmosphere) in the API rows
and guides, and softens "digit-for-digit" to "the standard's printed
precision" wherever it covered Annex E, whose final level differs only by
the standard's own pre-rounding. ES pages now use the /es/ link prefix
consistently. Code nits from the review: dead arg > 1 guard removed
(z > 0 implies arg >= 3), _with_advisory uses dataclasses.replace, and the
float-keyed _PRIME_BY_BAND gets a safety comment. llms files regenerated.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: validate propagation/exposure inputs and docs lint (PR review)
Addresses the PR #89 bot review:
- Barrier.__post_init__ rejects negative edge distances and a zero
edge_separation (which previously divided by zero in the C3 double-
diffraction factor); Task.__post_init__ rejects empty samples and a
non-positive duration.
- ground_attenuation and barrier_attenuation reject non-positive
frequencies (a zero frequency gave an infinite wavelength / division by
zero); ground_attenuation also checks a positive distance and
non-negative heights. job_based_exposure rejects a non-positive
sample_duration_hours.
- Rewrite the ISO 9613-2 7.3.2 closed form in the guides and API tables so
Markdownlint no longer parses `(...)[...]` as a reversed link (MD011).
- Regression tests for every new guard; docstrings note the new raises.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
Outdoor sound propagation and occupational noise exposure (ISO 9613-1, ISO 9613-2, ISO 9612) (#89)
* feat: ISO 9613-1 atmospheric sound absorption
Full alpha(f, T, RH, p) model per ISO 9613-1:1993 clauses 6.2-6.4:
oxygen/nitrogen relaxation frequencies, water-vapour molar
concentration from relative humidity, classical + rotational +
vibrational terms. Validated against a 13-point Table 1 grid
(worst deviation 0.39 %, rounding-limited, vs the standard's
stated +/-10 % accuracy) with the exact midband convention of
Eq. (6) Note 5. air_attenuation_m() feeds the ISO 354 m parameter
directly, closing the user-supplied gap. Two conformance checks
added (34/34).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: C1 review nits — test name and comment direction
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: extend ISO 9613-1 Table 1 oracle against the full standard text
The full 37-page ISO 9613-1:1993 text (now in hand) confirms every
implemented constant of Eqs. (3)-(6), the Annex B psychrometric
conversion and the clause 4.2 reference conditions exactly as coded.
Oracle extended from 13 to 23 Table 1 points, adding the 20-50 degC
sub-tables 1(i)-1(p) unavailable in the interim source. Worst
deviation unchanged at 0.385 % (rounding-limited).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9613-2 outdoor sound propagation
Implement the ISO 9613-2:1996 general method for octave-band outdoor sound
attenuation: geometrical divergence (Eq. 7), atmospheric absorption (Eq. 8,
via ISO 9613-1 air_absorption), ground effect (general per-region method of
7.3.1 with the Table 3 a'/b'/c'/d' functions, Eq. 9, plus the alternative
method of 7.3.2, Eq. 10, and the DOmega index Eq. 11), and screening (Eq. 12-18
with the C2/C3 factors, single/double diffraction, Kmet and the 20/25 dB caps).
Adds the Cmet meteorological correction (Eq. 21/22) and the LfT(DW)=Lw+Dc-A
receiver-level composition (Eq. 3/6). Frozen dataclass result exposes the
per-term breakdown (Adiv/Aatm/Agr/Abar). New module, tests and exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9612 occupational noise exposure strategies and uncertainty
Add phonometry.occupational_exposure implementing the three ISO 9612:2009
measurement strategies and the normative Annex C uncertainty budget:
- task_based_exposure (Clause 9): per-task energy average (Eq 7), task
contributions (Eq 8), daily level (Eq 9/10); uncertainty Eq C.3 with
sampling u1a (Eq C.6), duration u1b (Eq C.7) and sensitivity coefficients
c1a (Eq C.4) / c1b (Eq C.5).
- job_based_exposure (Clause 10): effective-day energy average (Eq 11),
daily level (Eq 12); Table 1 minimum-duration check; uncertainty Eq C.9.
- full_day_exposure (Clause 11): whole-day averaging (Eq 11/13) with the
Clause 11.3 three-measurement / 3 dB spread rule.
- Table C.4 (job/full-day c1*u1, bilinear interpolation), Table C.5 (u2),
u3 = 1.0 dB, coverage factor k = 1.65 (one-sided 95 %).
Frozen dataclasses (Task, TaskContribution, ExposureResult), ExposureWarning
advisories for the sampling rules, and exports appended to __init__.
Tests reproduce the Annex D (task), E (job) and F (full-day) worked examples
to the standard's precision, plus closed-form oracles (single 85 dB/8 h task
= 85; equal-level tasks; -3.01 dB per halved duration; k = 1.65) and the
Table C.4 / Table 1 lookups. make check green: 1167 passed, 12 skipped.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 9612 review corrections — Table C.4 digits and Eq C.7 denominator
Two Table C.4 cells verified against the page image at 200 dpi and
corrected (N=6/u1=3.5: 3.4 -> 3.3; N=20/u1=2.0: 0.6 -> 0.5), the test
that echoed the wrong N=6 cell now pins the printed value plus the
corrected N=20 cell. The duration_samples branch of Eq C.7 divides by
J(J-1) like Eq C.6 (standard error of the mean), with a regression test
pinning u1b = 1.0 h for samples (4, 6) h. Module docstring now states
the Lp,Cpeak uncertainty scope cut (Table C.5, NOTE 1).
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* test: ISO 9613-2 and ISO 9612 conformance checks
Add a new "Outdoor propagation & occupational exposure" conformance domain
with seven closed-form / worked-example checks backed by shared constants in
tests/reference_data.py:
- ISO 9613-2:1996 Eq. (7) geometrical divergence Adiv = 51 dB at 100 m.
- ISO 9613-2:1996 Table 3 ground limit b'(0) = 10,1 -> Agr(250 Hz) = 17,2 dB
(porous ground, hs = hr = 0, dp -> inf).
- ISO 9613-2:1996 clause 7.4 single/double diffraction 20/25 dB caps.
- ISO 9612:2009 Annex D/E/F daily exposure LEX,8h and expanded uncertainty U
(84,3/2,7, 88,1/3,8, 90,1/3,4 dB), the Task objects rebuilt from the shared
input table.
Registry grows 34 -> 41 checks across 8 domains; docs/CONFORMANCE.md
regenerated via make conformance. Registration and reference-data consistency
tests pin the constants to the published values.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: figures for outdoor propagation and occupational exposure
Add four documentation figures (each EN/ES x light/dark) plus a setup diagram:
- air_absorption_alpha: ISO 9613-1 alpha(f) over frequency at four
temperature/humidity combinations (relaxation roll-off, f^2 growth).
- outdoor_attenuation_breakdown: ISO 9613-2 per-term stacked bar (Adiv, Aatm,
Agr, Abar) with the total A, for a 200 m path over porous ground with a 4 m
barrier.
- exposure_uncertainty: ISO 9612 Annex D task contributions with the daily
LEX,8h and the one-sided 95 % upper limit LEX,8h + U.
- diagram_outdoor_geometry: source-barrier-receiver geometry (dss/dsr/z, the
blocked direct ray and the diffracted ray over the top edge).
Spanish translations added to the generate_graphs / generate_diagrams
dictionaries (decimal commas, UNE terminology). Every image visually audited.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: ISO 9613-1/2 outdoor propagation guide and ISO 9612 exposure (EN)
Add the didactic Outdoor Sound Propagation guide (docs/outdoor-propagation.md)
covering ISO 9613-1 atmospheric absorption and the ISO 9613-2 general method
(divergence, atmospheric, ground and barrier terms, the OutdoorAttenuation
breakdown, the alternative 7.3.2 ground method, Cmet), with executed snippets
and honest scope notes (Amisc/reflections not implemented, 7.3.2 not
auto-wired, per-band Cmet a convenience). Extend the Levels guide with the
ISO 9612 occupational-exposure section (task/job/full-day strategies, the
C.6 I(I-1) vs C.12 N-1 asymmetry, Table C.4, k = 1,65, LEX,8h + U upper limit,
Lp,Cpeak uncertainty out of scope), reproducing the Annex D/E/F worked
examples.
Add the matching theory sections, API-reference rows for every new public
name, README feature list + docs table, docs index and CHANGELOG entries.
llms-full.txt / llms.txt regenerated (make llms) with the new page wired into
gen_llms.py. GitHub-safe math throughout; every snippet executed with pasted
outputs.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: outdoor propagation and exposure site twins (EN + ES)
Add the English and Spanish Starlight twins of the new content:
- guides/outdoor-propagation.md (EN + ES) — code-identical snippets to the
docs page; Spanish prose uses UNE terminology ("ponderación temporal"),
decimal commas outside math and code, and the _es figure variants.
- The ISO 9612 section added to guides/levels.md (EN + ES).
- reference/theory.md and reference/api.md rows (EN + ES).
- Landing cards and standards list bumped 34 -> 37 (index.mdx EN + ES);
guides/outdoor-propagation added to the sidebar.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: final branch review — API rows, precision phrasing and ES links
Adds the five missing public-symbol rows (TaskContribution,
table_c4_contribution, minimum_cumulative_duration_hours, COVERAGE_FACTOR,
INSTRUMENT_U2) to the three API references, states the ISO 9613-2 default
atmosphere (20 °C / 70 %, a Table 2 reference atmosphere) in the API rows
and guides, and softens "digit-for-digit" to "the standard's printed
precision" wherever it covered Annex E, whose final level differs only by
the standard's own pre-rounding. ES pages now use the /es/ link prefix
consistently. Code nits from the review: dead arg > 1 guard removed
(z > 0 implies arg >= 3), _with_advisory uses dataclasses.replace, and the
float-keyed _PRIME_BY_BAND gets a safety comment. llms files regenerated.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: validate propagation/exposure inputs and docs lint (PR review)
Addresses the PR #89 bot review:
- Barrier.__post_init__ rejects negative edge distances and a zero
edge_separation (which previously divided by zero in the C3 double-
diffraction factor); Task.__post_init__ rejects empty samples and a
non-positive duration.
- ground_attenuation and barrier_attenuation reject non-positive
frequencies (a zero frequency gave an infinite wavelength / division by
zero); ground_attenuation also checks a positive distance and
non-negative heights. job_based_exposure rejects a non-positive
sample_duration_hours.
- Rewrite the ISO 9613-2 7.3.2 closed form in the guides and API tables so
Markdownlint no longer parses `(...)[...]` as a reversed link (MD011).
- Regression tests for every new guard; docstrings note the new raises.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
Outdoor sound propagation and occupational noise exposure (ISO 9613-1, ISO 9613-2, ISO 9612) (#89)
* feat: ISO 9613-1 atmospheric sound absorption
Full alpha(f, T, RH, p) model per ISO 9613-1:1993 clauses 6.2-6.4:
oxygen/nitrogen relaxation frequencies, water-vapour molar
concentration from relative humidity, classical + rotational +
vibrational terms. Validated against a 13-point Table 1 grid
(worst deviation 0.39 %, rounding-limited, vs the standard's
stated +/-10 % accuracy) with the exact midband convention of
Eq. (6) Note 5. air_attenuation_m() feeds the ISO 354 m parameter
directly, closing the user-supplied gap. Two conformance checks
added (34/34).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* refactor: C1 review nits — test name and comment direction
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: extend ISO 9613-1 Table 1 oracle against the full standard text
The full 37-page ISO 9613-1:1993 text (now in hand) confirms every
implemented constant of Eqs. (3)-(6), the Annex B psychrometric
conversion and the clause 4.2 reference conditions exactly as coded.
Oracle extended from 13 to 23 Table 1 points, adding the 20-50 degC
sub-tables 1(i)-1(p) unavailable in the interim source. Worst
deviation unchanged at 0.385 % (rounding-limited).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9613-2 outdoor sound propagation
Implement the ISO 9613-2:1996 general method for octave-band outdoor sound
attenuation: geometrical divergence (Eq. 7), atmospheric absorption (Eq. 8,
via ISO 9613-1 air_absorption), ground effect (general per-region method of
7.3.1 with the Table 3 a'/b'/c'/d' functions, Eq. 9, plus the alternative
method of 7.3.2, Eq. 10, and the DOmega index Eq. 11), and screening (Eq. 12-18
with the C2/C3 factors, single/double diffraction, Kmet and the 20/25 dB caps).
Adds the Cmet meteorological correction (Eq. 21/22) and the LfT(DW)=Lw+Dc-A
receiver-level composition (Eq. 3/6). Frozen dataclass result exposes the
per-term breakdown (Adiv/Aatm/Agr/Abar). New module, tests and exports.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9612 occupational noise exposure strategies and uncertainty
Add phonometry.occupational_exposure implementing the three ISO 9612:2009
measurement strategies and the normative Annex C uncertainty budget:
- task_based_exposure (Clause 9): per-task energy average (Eq 7), task
contributions (Eq 8), daily level (Eq 9/10); uncertainty Eq C.3 with
sampling u1a (Eq C.6), duration u1b (Eq C.7) and sensitivity coefficients
c1a (Eq C.4) / c1b (Eq C.5).
- job_based_exposure (Clause 10): effective-day energy average (Eq 11),
daily level (Eq 12); Table 1 minimum-duration check; uncertainty Eq C.9.
- full_day_exposure (Clause 11): whole-day averaging (Eq 11/13) with the
Clause 11.3 three-measurement / 3 dB spread rule.
- Table C.4 (job/full-day c1*u1, bilinear interpolation), Table C.5 (u2),
u3 = 1.0 dB, coverage factor k = 1.65 (one-sided 95 %).
Frozen dataclasses (Task, TaskContribution, ExposureResult), ExposureWarning
advisories for the sampling rules, and exports appended to __init__.
Tests reproduce the Annex D (task), E (job) and F (full-day) worked examples
to the standard's precision, plus closed-form oracles (single 85 dB/8 h task
= 85; equal-level tasks; -3.01 dB per halved duration; k = 1.65) and the
Table C.4 / Table 1 lookups. make check green: 1167 passed, 12 skipped.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 9612 review corrections — Table C.4 digits and Eq C.7 denominator
Two Table C.4 cells verified against the page image at 200 dpi and
corrected (N=6/u1=3.5: 3.4 -> 3.3; N=20/u1=2.0: 0.6 -> 0.5), the test
that echoed the wrong N=6 cell now pins the printed value plus the
corrected N=20 cell. The duration_samples branch of Eq C.7 divides by
J(J-1) like Eq C.6 (standard error of the mean), with a regression test
pinning u1b = 1.0 h for samples (4, 6) h. Module docstring now states
the Lp,Cpeak uncertainty scope cut (Table C.5, NOTE 1).
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* test: ISO 9613-2 and ISO 9612 conformance checks
Add a new "Outdoor propagation & occupational exposure" conformance domain
with seven closed-form / worked-example checks backed by shared constants in
tests/reference_data.py:
- ISO 9613-2:1996 Eq. (7) geometrical divergence Adiv = 51 dB at 100 m.
- ISO 9613-2:1996 Table 3 ground limit b'(0) = 10,1 -> Agr(250 Hz) = 17,2 dB
(porous ground, hs = hr = 0, dp -> inf).
- ISO 9613-2:1996 clause 7.4 single/double diffraction 20/25 dB caps.
- ISO 9612:2009 Annex D/E/F daily exposure LEX,8h and expanded uncertainty U
(84,3/2,7, 88,1/3,8, 90,1/3,4 dB), the Task objects rebuilt from the shared
input table.
Registry grows 34 -> 41 checks across 8 domains; docs/CONFORMANCE.md
regenerated via make conformance. Registration and reference-data consistency
tests pin the constants to the published values.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: figures for outdoor propagation and occupational exposure
Add four documentation figures (each EN/ES x light/dark) plus a setup diagram:
- air_absorption_alpha: ISO 9613-1 alpha(f) over frequency at four
temperature/humidity combinations (relaxation roll-off, f^2 growth).
- outdoor_attenuation_breakdown: ISO 9613-2 per-term stacked bar (Adiv, Aatm,
Agr, Abar) with the total A, for a 200 m path over porous ground with a 4 m
barrier.
- exposure_uncertainty: ISO 9612 Annex D task contributions with the daily
LEX,8h and the one-sided 95 % upper limit LEX,8h + U.
- diagram_outdoor_geometry: source-barrier-receiver geometry (dss/dsr/z, the
blocked direct ray and the diffracted ray over the top edge).
Spanish translations added to the generate_graphs / generate_diagrams
dictionaries (decimal commas, UNE terminology). Every image visually audited.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: ISO 9613-1/2 outdoor propagation guide and ISO 9612 exposure (EN)
Add the didactic Outdoor Sound Propagation guide (docs/outdoor-propagation.md)
covering ISO 9613-1 atmospheric absorption and the ISO 9613-2 general method
(divergence, atmospheric, ground and barrier terms, the OutdoorAttenuation
breakdown, the alternative 7.3.2 ground method, Cmet), with executed snippets
and honest scope notes (Amisc/reflections not implemented, 7.3.2 not
auto-wired, per-band Cmet a convenience). Extend the Levels guide with the
ISO 9612 occupational-exposure section (task/job/full-day strategies, the
C.6 I(I-1) vs C.12 N-1 asymmetry, Table C.4, k = 1,65, LEX,8h + U upper limit,
Lp,Cpeak uncertainty out of scope), reproducing the Annex D/E/F worked
examples.
Add the matching theory sections, API-reference rows for every new public
name, README feature list + docs table, docs index and CHANGELOG entries.
llms-full.txt / llms.txt regenerated (make llms) with the new page wired into
gen_llms.py. GitHub-safe math throughout; every snippet executed with pasted
outputs.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* docs: outdoor propagation and exposure site twins (EN + ES)
Add the English and Spanish Starlight twins of the new content:
- guides/outdoor-propagation.md (EN + ES) — code-identical snippets to the
docs page; Spanish prose uses UNE terminology ("ponderación temporal"),
decimal commas outside math and code, and the _es figure variants.
- The ISO 9612 section added to guides/levels.md (EN + ES).
- reference/theory.md and reference/api.md rows (EN + ES).
- Landing cards and standards list bumped 34 -> 37 (index.mdx EN + ES);
guides/outdoor-propagation added to the sidebar.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: final branch review — API rows, precision phrasing and ES links
Adds the five missing public-symbol rows (TaskContribution,
table_c4_contribution, minimum_cumulative_duration_hours, COVERAGE_FACTOR,
INSTRUMENT_U2) to the three API references, states the ISO 9613-2 default
atmosphere (20 °C / 70 %, a Table 2 reference atmosphere) in the API rows
and guides, and softens "digit-for-digit" to "the standard's printed
precision" wherever it covered Annex E, whose final level differs only by
the standard's own pre-rounding. ES pages now use the /es/ link prefix
consistently. Code nits from the review: dead arg > 1 guard removed
(z > 0 implies arg >= 3), _with_advisory uses dataclasses.replace, and the
float-keyed _PRIME_BY_BAND gets a safety comment. llms files regenerated.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
* fix: validate propagation/exposure inputs and docs lint (PR review)
Addresses the PR #89 bot review:
- Barrier.__post_init__ rejects negative edge distances and a zero
edge_separation (which previously divided by zero in the C3 double-
diffraction factor); Task.__post_init__ rejects empty samples and a
non-positive duration.
- ground_attenuation and barrier_attenuation reject non-positive
frequencies (a zero frequency gave an infinite wavelength / division by
zero); ground_attenuation also checks a positive distance and
non-negative heights. job_based_exposure rejects a non-positive
sample_duration_hours.
- Rewrite the ISO 9613-2 7.3.2 closed form in the guides and API tables so
Markdownlint no longer parses `(...)[...]` as a reversed link (MD011).
- Regression tests for every new guard; docstrings note the new raises.
Claude-Session: https://claude.ai/code/session_01HUHMx4dxDes2t5UPQ25djP
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Psychoacoustics, speech intelligibility and sound intensity (ISO 532-1, DIN 45692, IEC 60268-16, IEC 61043) (#80)
* test: ISO 532-1 Annex B expected-value fixtures
Expected N (stationary, with the Annex tolerances) and Nmax/N5
(time-varying, 5% tolerance) for all 25 normative test signals,
extracted from the results workbooks of the freely downloadable
ISO 532-1:2017 electronic attachment, plus the Test signal 1
third-octave input levels.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: Zwicker loudness per ISO 532-1:2017 (stationary and time-varying)
Clean-room Python port of the normative Annex A.4 reference
implementation: all twelve numeric tables (A.1-A.9) verified
digit-exact against the C source in _zwicker_data.py, the Table A.1/A.2
third-octave filterbank, the level-dependent weighting, critical-band
and core-loudness stages, the exact f_nl nonlinear temporal-decay state
machine, temporal weighting and the 500 Hz loudness-vs-time trace with
Nmax/N5/N10. API: loudness_zwicker(x, fs, field=, stationary=) and
loudness_zwicker_from_spectrum(levels, field=) returning a frozen
ZwickerLoudness dataclass.
Conformance (Annex B, from the freely downloadable ISO electronic
attachment): Test signal 1 stationary spectrum matches the published N
to all printed digits (83.2957 sone); regenerated B.3 tones sit inside
the workbook tolerance intervals; the B.4 tone-pulse WAVs (included,
small) must keep >=99% of the N(t) trace inside the per-sample
normative tolerance band - the workbook header N5 values are not
reproducible from their own published traces and are documented as not
asserted. B.5 technical recordings run when ISO532_1_TESTDATA points
at the attachment.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: sharpness per DIN 45692:2009 (acum)
sharpness_din(x, fs, field=, method=) and
sharpness_din_from_specific(specific) implement Equation (1) - the
g(z)-weighted first moment of the ISO 532-1 specific-loudness pattern -
with the normalization constant k derived numerically from the clause 6
standard test signal (critical-band-wide 920-1080 Hz noise at 60 dB ->
exactly 1.00 acum; the derived k = 0.108 sits inside the normative
0.105 <= k < 0.115 window). The informative Annex B variants of Aures
and von Bismarck are selectable. Conformance tests: reference identity,
k range, and Table A.2 targets at four centre frequencies using
critical-band noises equalized to 4 sone (Tabelle A.1 band edges),
within the clause 6 tolerance of 5 % or 0.05 acum.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: annotate Aures weighting return for strict mypy
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: robust short-signal handling and consistent peak pattern in Zwicker port
Findings surfaced by review bots on an accidental early diff: (1) inputs
shorter than one 500 Hz output sample crashed on an empty percentile
buffer - the minimum-length validation now requires a full output step;
(2) the returned specific pattern was picked with the un-decimated
argmax while Nmax/N5/N10 come from the decimated trace - both now use
the same decimated instant (regression tests added; note the pattern
integral only equals Nmax for steady signals, since N(t) is temporally
weighted).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: STI/STIPA (IEC 60268-16 Ed. 5) and p-p sound intensity (IEC 61043 + ISO 9614-1)
STI: sti_from_impulse_response (indirect method: IEC 61260 octave bank,
Schroeder MTF at the 14 modulation frequencies, optional SNR/masking/
reception-threshold corrections per Tables A.2/A.3, +-15 dB clip, male
alpha/beta weighting), stipa() direct method and an Ed. 5-conformant
stipa_signal() generator using the revised A.6.1 male spectrum. Ed. 4
PDF is the primary source; Ed. 5 deltas are source-attributed in the
constants (MathWorks Ed. 5 compliance doc, zawi01/stipa - numeric
values only, no GPL code). Verified: the six A.2.2 weighting pairs
exact to 0.001, eleven m<->STI pairs, masking control points,
exponential decays vs the Schroeder closed form at four T60 values,
STIPA loop-back 0.998 and monotonic SNR degradation.
Intensity: sound_intensity() cross-spectral p-p method
(I = -Im{G12}/(2pi f rho dr)) with octave/third-octave integration,
pressure-intensity index, direction, finite-difference bias correction
validated against IEC 61043 Table 3, plus ISO 9614-1 Annex A field
indicators (F2/F3/F4) and the dynamic-capability criterion (Ld = dpI0-K,
Table 1). Verified against exact plane-wave and standing-wave physics.
415 tests, mypy strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: new guide pages, refreshed landing and README for the expanded scope
Psychoacoustics & Speech Intelligibility and Sound Intensity guide pages
(EN, docs + site with sidebar entries), the ISO 1996-2 and ECMA-74
position diagrams finally embedded in the levels guide (EN/ES), and the
outdated landing page (EN/ES), README highlights/docs table and
changelog brought up to the real scope - the hero and cards now name
the thirteen standards under conformance test instead of the original
two.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic pages, figures, diagrams and theory for psychoacoustics and intensity
Three new audited figures in four language/theme variants (specific
loudness pattern narrowband-vs-broadband, STI vs T60 with the Annex F
rating bands against the analytic Schroeder curve, and plane-vs-standing
wave intensity panels showing the pressure-intensity index), two new
setup diagrams (p-p probe with the spacer dimension, STI measurement
chain), Spanish twins of the two new guide pages, three theory sections
(Zwicker chain, MTF/STI math, intensity estimator with its bias) in
EN docs, EN site and ES site with GitHub-safe math, and API rows for
all thirteen new exports in the three reference tables.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* test: track the ISO 532-1 Annex B.4 pulse WAVs (were gitignored)
The global *.wav ignore silently excluded the four normative tone-pulse
fixtures, so CI failed with FileNotFoundError on every OS while local
runs passed against the untracked files. Force-added with an explicit
gitignore exception.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address PR 80 review round 1
- docs: use the real dynamic_capability_index signature and keep the
intensity example bands under the 12 mm spacer validity ceiling
- docs: calibration example wording (raw recording, not already-Pa)
- changelog: merge the duplicated Unreleased Added sections
- loudness: reject non-finite inputs and pathological resampling ratios
(gcd-1 rates like 44101 Hz) with clear errors, regression-tested
- tests: anchor the Aures/von Bismarck variants to the 1 acum reference
within 0.05 acum instead of a loose sanity bound
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Didactic documentation: theory everywhere, bilingual figures, setup diagrams, parameter tables (#77)
* docs: harden diagram engine per visual audit
- dim() draws real witness lines from the measured points to the offset
dimension line (the offset=0 path emitted zero-length lines); vertical
labels sit left of the line, clear of masts and figures
- env diagram: the 4 m dimension now measures the mic axis itself and
the flush-mounted label moved to the clear zone between masts
- tonality top view: the 1.00 m dimension connects face and microphone
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual diagram variants (EN/ES x light/dark)
Every setup diagram is now emitted in four variants; Spanish strings
(including decimal commas) come from a translation table applied by the
SVG engine, and layouts were adjusted where the longer Spanish labels
collided (env titles, processing-chain box width, calibration output
label, tonality dimension label side).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: bilingual figure variants for the ES site (EN/ES x light/dark)
generate_graphs.py now emits every figure in four variants: a Spanish
translation table (~75 exact strings + parametrized patterns) is applied
to the figure's Text artists at savefig time, so the generator functions
stay single-language internally. Spanish output uses UNE terminology
(ponderación temporal, líneas isofónicas, fonios, ráfaga) and a uniform
decimal comma (annotations and tick labels included); code identifiers
and normative mode names (Fast/Slow/Impulse) stay untranslated. The ES
site pages now reference the _es/_es_dark variants (56 URLs). The ES set
passed a 10-figure visual audit (10/10 approved, no blockers).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic calibration page - theory, setup diagram, stability figure, parameter table
Adds the sensitivity-factor derivation with the calibration-chain SVG,
a new autogenerated calibration_stability figure (stable vs 3% AM tone
against the IEC 60942:2017 class 1 deviation band; 4 language/theme
variants; the ES decimal-comma pass now preserves clause numbers like
5.3.3), and a full parameter table for calculate_sensitivity - EN and
ES in parity.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: SEL concept, Lden 24h profile and annotated TNR spectrum figures
Three new didactic figures for the levels guide, each in four
language/theme variants: sel_concept (pass-by event vs its Leq and the
equal-energy 1 s SEL block, dBFS mode), lden_profile (synthetic urban
24 h LAeq with colored day/evening/night bands and the +5/+10 weighted
period levels clearly separated from the composite Lden), and
tonality_spectrum (averaged Hann spectrum with the critical band, the
detected tone and the live TNR value vs its criterion, computed by the
library itself).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: didactic levels guide, theory extensions and refreshed why-phonometry
- levels guide (EN docs+site): energy-mean rationale for Leq, percentile
semantics for LN, SEL and noise-dose theory with the new figures
embedded, TNR critical-band explanation with the annotated spectrum,
Lden profile figure, and parameter tables (type/units/range/default)
for every level function including the spectrogram
- theory page: five new sections (G-weighting pole/zero derivation,
ISO 226 formulae, ECMA-418-1 TNR/PR math, event/dose metrics,
ISO 1996-1 descriptors) with cross-references to the guides
- why-phonometry: rewritten around the conformance-testing story with
the per-standard verification table and honest ecosystem positioning
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: weighting/time-weighting theory and parameter tables; fix math-block delimiters
The physiological origin of A/C (inverted 40/100-phon contours, the four
IEC corner frequencies) and the exponential-detector derivation with the
tau semantics, each with full parameter tables. Display math inserted by
the docs expansion now always uses block-style $$ delimiters on their
own lines - mid-line multi-line $$ blocks silently derailed remark
parsing and truncated every heading after them (caught because the
built pages lost their anchor ids); also replaced a raw < in a table.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: processing-chain and multirate diagrams, filter-bank math, streaming patterns
- getting-started embeds the processing-chain diagram as a guided map of
the guides
- filter-banks gains the IEC 61260-1 base-10 band math (G, fm, band
edges), a new multirate-decimation diagram (d5, four language/theme
variants) and the full octavefilter/OctaveFilterBank parameter table
- block-processing gains the canonical real-time level-meter loop
(validated against the actual API - TimeWeighting is inherently
stateful) and a stateful-constraints table
- multichannel gains the accepted-shapes table
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: Spanish parity for the didactic expansion
Every enriched page now has its Spanish twin: levels (theory, three new
figures via _es variants, six parameter tables), weighting and
time-weighting (curve-origin and exponential-detector sections),
filter-banks (fractional-band math, multirate diagram, full parameter
table - terminology unified on 'decimación'), getting-started
(processing-chain map), block-processing (real-time meter pattern and
stateful constraints), multichannel (shapes table), theory (five new
sections) and a full rewrite of why-phonometry around the conformance
story. API reference now covers all 27 public exports in EN and ES
(added ToneAssessment and CalibrationWarning rows). UNE terminology and
Spanish decimal commas throughout; site builds with all links valid.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: audited fixes - Spanish tick commas and multirate note
Final visual-audit round: the d5 diagram now shows the no-decimation
note on the 16 kHz row in both languages, and Spanish figures render
every numeric tick with a decimal comma (FixedFormatter sequences are
rewritten in place; set_xticklabels-style FuncFormatters and plain
linear ScalarFormatters are wrapped - the first naive wrapper broke
ScalarFormatter ticks entirely and was caught visually).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs(site): language selector in the mobile header, scrollable display math
Custom Header component (default markup plus a compact icon-only
LanguageSelect visible below the md breakpoint, where Starlight hides
the whole right group behind the hamburger menu) and overflow-x on
katex-display so wide formulas scroll inside their box on phones.
Verified with Playwright at 390 px in EN and ES.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: address review feedback on the didactic docs
- levels tables: spectrogram calibration_factor/dbfs marked constructor-
only, overlap range as 0 <= overlap < 1, composite hours constraints,
ln_levels shared-semantics row filled; ES translation leftovers and
the 'delante' typo fixed
- block-processing: y[..., -1] so the meter loop is multichannel-safe;
high_accuracy wording matches the real behavior (default resolves to
False, explicit True raises)
- API: CalibrationWarning row states the fs/validate preconditions (3 files)
- weighting: high_accuracy default column and oversampling claim made
precise (8x cap; silently ignored for G); ES row in parity
- filter-banks: 25 Hz relative bandwidth corrected to 0.024% of Nyquist
(EN/ES); verify_filter_class classes documented as 1/2/None
- generate_graphs: dropped the global plt.savefig monkey-patch - the
translation now runs inside themed_path(), which every generator
already calls at save time (verified output identical)
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
feat: measurement uncertainty (GUM ISO/IEC Guide 98-3:2008 + Monte Carlo Supplement 1) (#102)
Adds a `phonometry.uncertainty` module implementing the two propagation methods of the GUM:
* Law of propagation of uncertainty (ISO/IEC Guide 98-3:2008, clause 5) — `combine_uncertainty` builds the combined standard uncertainty from central-difference sensitivity coefficients, with optional input correlations (validated for shape, symmetry, unit diagonal and positive-semidefiniteness), Welch-Satterthwaite effective degrees of freedom (Annex G.4) and the expanded uncertainty U = k*uc (clause 6).
* Monte Carlo method (ISO/IEC Guide 98-3-1:2008, Supplement 1, clause 7) — `monte_carlo` propagates the input PDFs and returns the estimate, its standard uncertainty and the probabilistically symmetric coverage interval (clause 7.7).
Type B quantities from a half-width: `rectangular` (a/sqrt3), `triangular` (a/sqrt6), `u_shaped` (a/sqrt2). Results expose `.expanded()` and `.plot()` (uncertainty budget).
Validated against the Guides' worked examples: additive uc=2.0 (Suppl. 1, 9.2), coverage factor k=2.92 at p=0.99/v=16 (Table G.2), Welch-Satterthwaite v_eff=40 (Annex G.4), Monte Carlo interval [-3.88, 3.88] (Suppl. 1, 9.2.3). Conformance 79/79.
Includes the budget/Monte-Carlo figure, the two-lane GUM-vs-Monte-Carlo diagram (EN/ES, light/dark), the repo doc and the EN/ES site guides under a new "Metrology & uncertainty" section.
feat: measurement uncertainty (GUM ISO/IEC Guide 98-3:2008 + Monte Carlo Supplement 1) (#102)
Adds a `phonometry.uncertainty` module implementing the two propagation methods of the GUM:
* Law of propagation of uncertainty (ISO/IEC Guide 98-3:2008, clause 5) — `combine_uncertainty` builds the combined standard uncertainty from central-difference sensitivity coefficients, with optional input correlations (validated for shape, symmetry, unit diagonal and positive-semidefiniteness), Welch-Satterthwaite effective degrees of freedom (Annex G.4) and the expanded uncertainty U = k*uc (clause 6).
* Monte Carlo method (ISO/IEC Guide 98-3-1:2008, Supplement 1, clause 7) — `monte_carlo` propagates the input PDFs and returns the estimate, its standard uncertainty and the probabilistically symmetric coverage interval (clause 7.7).
Type B quantities from a half-width: `rectangular` (a/sqrt3), `triangular` (a/sqrt6), `u_shaped` (a/sqrt2). Results expose `.expanded()` and `.plot()` (uncertainty budget).
Validated against the Guides' worked examples: additive uc=2.0 (Suppl. 1, 9.2), coverage factor k=2.92 at p=0.99/v=16 (Table G.2), Welch-Satterthwaite v_eff=40 (Annex G.4), Monte Carlo interval [-3.88, 3.88] (Suppl. 1, 9.2.3). Conformance 79/79.
Includes the budget/Monte-Carlo figure, the two-lane GUM-vs-Monte-Carlo diagram (EN/ES, light/dark), the repo doc and the EN/ES site guides under a new "Metrology & uncertainty" section.
feat: measurement uncertainty (GUM ISO/IEC Guide 98-3:2008 + Monte Carlo Supplement 1) (#102)
Adds a `phonometry.uncertainty` module implementing the two propagation methods of the GUM:
* Law of propagation of uncertainty (ISO/IEC Guide 98-3:2008, clause 5) — `combine_uncertainty` builds the combined standard uncertainty from central-difference sensitivity coefficients, with optional input correlations (validated for shape, symmetry, unit diagonal and positive-semidefiniteness), Welch-Satterthwaite effective degrees of freedom (Annex G.4) and the expanded uncertainty U = k*uc (clause 6).
* Monte Carlo method (ISO/IEC Guide 98-3-1:2008, Supplement 1, clause 7) — `monte_carlo` propagates the input PDFs and returns the estimate, its standard uncertainty and the probabilistically symmetric coverage interval (clause 7.7).
Type B quantities from a half-width: `rectangular` (a/sqrt3), `triangular` (a/sqrt6), `u_shaped` (a/sqrt2). Results expose `.expanded()` and `.plot()` (uncertainty budget).
Validated against the Guides' worked examples: additive uc=2.0 (Suppl. 1, 9.2), coverage factor k=2.92 at p=0.99/v=16 (Table G.2), Welch-Satterthwaite v_eff=40 (Annex G.4), Monte Carlo interval [-3.88, 3.88] (Suppl. 1, 9.2.3). Conformance 79/79.
Includes the budget/Monte-Carlo figure, the two-lane GUM-vs-Monte-Carlo diagram (EN/ES, light/dark), the repo doc and the EN/ES site guides under a new "Metrology & uncertainty" section.
feat: measurement uncertainty (GUM ISO/IEC Guide 98-3:2008 + Monte Carlo Supplement 1) (#102)
Adds a `phonometry.uncertainty` module implementing the two propagation methods of the GUM:
* Law of propagation of uncertainty (ISO/IEC Guide 98-3:2008, clause 5) — `combine_uncertainty` builds the combined standard uncertainty from central-difference sensitivity coefficients, with optional input correlations (validated for shape, symmetry, unit diagonal and positive-semidefiniteness), Welch-Satterthwaite effective degrees of freedom (Annex G.4) and the expanded uncertainty U = k*uc (clause 6).
* Monte Carlo method (ISO/IEC Guide 98-3-1:2008, Supplement 1, clause 7) — `monte_carlo` propagates the input PDFs and returns the estimate, its standard uncertainty and the probabilistically symmetric coverage interval (clause 7.7).
Type B quantities from a half-width: `rectangular` (a/sqrt3), `triangular` (a/sqrt6), `u_shaped` (a/sqrt2). Results expose `.expanded()` and `.plot()` (uncertainty budget).
Validated against the Guides' worked examples: additive uc=2.0 (Suppl. 1, 9.2), coverage factor k=2.92 at p=0.99/v=16 (Table G.2), Welch-Satterthwaite v_eff=40 (Annex G.4), Monte Carlo interval [-3.88, 3.88] (Suppl. 1, 9.2.3). Conformance 79/79.
Includes the budget/Monte-Carlo figure, the two-lane GUM-vs-Monte-Carlo diagram (EN/ES, light/dark), the repo doc and the EN/ES site guides under a new "Metrology & uncertainty" section.
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
Audit pass 11a: seven new documentation diagrams (#121)
* Audit pass 11a: seven new documentation diagrams
Add SVG flow diagrams for the seven topics the audit flagged as having no
schematic: the exponential-detector chain of the time weightings
(IEC 61672-1), stateful vs reset block processing, the multichannel
array-shape flow, the open-plan spatial-decay line (ISO 3382-3), the
ISO 12999-1 uncertainty pipeline, the ISO 11654 absorption-rating flow and
the Zwicker loudness-model chain (ISO 532-1).
Each is generated deterministically by generate_diagrams.py in the four
EN/ES x light/dark variants, with every Spanish label added to the _ES
table (decimals localised to commas), and embedded in the repo docs and
both site trees beside the existing worked-example plots.
* Fix ISO 532-1 table citations in the Zwicker diagram
Review of the diagram against loudness_zwicker.py found two mislabelled
tables: the equal-loudness correction and lower-critical-band grouping is
Table A.3 (not A.4), and the threshold in quiet LTQ is Table A.6 (not A.3).
Reassign the a0/DDF/LTQ corrections to the core-loudness step (Tables
A.4-A.7) where they belong, update the Spanish labels, and align the ES
psychoacoustics alt text with the guide's own term "sonos" (was "sonios").
feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000) (#125)
* feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000)
New module phonometry.facade_prediction implementing the two building-envelope
prediction directions on a shared energy summation of element transmission
factors:
- EN 12354-3 (outdoor -> indoor): facade_sound_reduction() -> apparent R'
(Formula 10), the loudspeaker/traffic indices R45/Rtr,s (11/12) and the
standardized level difference D2m,nT (13), with ISO 717-1 single numbers.
- EN 12354-4 (indoor -> outdoor): radiated_sound_power() -> segment R' and the
radiated power level LW (Formula 2), plus the simplified Annex E outdoor
attenuation (outdoor_attenuation / outdoor_level).
FacadeElement models an area element (R), a small element / air path (Dn,e) or
an opening (insertion loss); FacadePredictionResult and RadiatedPowerResult are
frozen dataclasses exposing .plot().
Validated clean-room against the Part 3 Annex F and Part 4 Annex G worked
examples: the low octave bands, every single-number rating and the whole Annex E
propagation reproduce the published values exactly (3 new conformance checks,
98/98). The standards' own worked examples carry documented internal rounding
inconsistencies at the higher bands, tracked in the reference-data notes.
Adds the EN/ES facade_prediction figure (SVG, deterministic), the EN 12354-3/-4
section in the building-acoustics guide (EN + ES site), API-reference rows and
regenerated CONFORMANCE.md / llms-full.txt.
* fix: avoid assert for type-narrowing in FacadeElement.tau (bandit B101)
The rest of src/ avoids assert (removed under python -O); fetch the single
non-None quantity via getattr, matching the _band_count pattern, so mypy is
satisfied without an assert.
* review: harden facade_prediction per bot review
- Fix a real bug: _apparent_reduction keyed transmission factors by element
name in a dict, so two elements sharing a name silently dropped one from the
R' sum. Sum over the element list and require unique names (they key the
per-element result). (gemini)
- outdoor_level: allow NumPy broadcasting (scalar Atot vs per-side LW array).
- Validate 'frequencies' / 'octave_bands' length against the band count. (Copilot)
- Guard tau() against non-positive total_area; include the element kind in
finite-check error labels. (gemini/Copilot)
- Docstring: bands accepts 'third-octave' (not 'third'). (Copilot)
- Tests for all of the above.
* docs: address CodeRabbit review on facade prediction docs
- Fix worked-example prose: the snippet has a window + a skylight, not
'two windows' (docs + EN/ES site guides).
- Complete the façade parameter table with facade_sound_reduction(frequencies),
radiated_sound_power(octave_bands) and outdoor_level() rows (docs + EN/ES).
- Document the optional 'frequencies' parameter in the facade_sound_reduction
API-reference rows (docs + EN/ES).
- Regenerate llms-full.txt.
The Major duplicate-name finding was already fixed in af23efc.
feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000) (#125)
* feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000)
New module phonometry.facade_prediction implementing the two building-envelope
prediction directions on a shared energy summation of element transmission
factors:
- EN 12354-3 (outdoor -> indoor): facade_sound_reduction() -> apparent R'
(Formula 10), the loudspeaker/traffic indices R45/Rtr,s (11/12) and the
standardized level difference D2m,nT (13), with ISO 717-1 single numbers.
- EN 12354-4 (indoor -> outdoor): radiated_sound_power() -> segment R' and the
radiated power level LW (Formula 2), plus the simplified Annex E outdoor
attenuation (outdoor_attenuation / outdoor_level).
FacadeElement models an area element (R), a small element / air path (Dn,e) or
an opening (insertion loss); FacadePredictionResult and RadiatedPowerResult are
frozen dataclasses exposing .plot().
Validated clean-room against the Part 3 Annex F and Part 4 Annex G worked
examples: the low octave bands, every single-number rating and the whole Annex E
propagation reproduce the published values exactly (3 new conformance checks,
98/98). The standards' own worked examples carry documented internal rounding
inconsistencies at the higher bands, tracked in the reference-data notes.
Adds the EN/ES facade_prediction figure (SVG, deterministic), the EN 12354-3/-4
section in the building-acoustics guide (EN + ES site), API-reference rows and
regenerated CONFORMANCE.md / llms-full.txt.
* fix: avoid assert for type-narrowing in FacadeElement.tau (bandit B101)
The rest of src/ avoids assert (removed under python -O); fetch the single
non-None quantity via getattr, matching the _band_count pattern, so mypy is
satisfied without an assert.
* review: harden facade_prediction per bot review
- Fix a real bug: _apparent_reduction keyed transmission factors by element
name in a dict, so two elements sharing a name silently dropped one from the
R' sum. Sum over the element list and require unique names (they key the
per-element result). (gemini)
- outdoor_level: allow NumPy broadcasting (scalar Atot vs per-side LW array).
- Validate 'frequencies' / 'octave_bands' length against the band count. (Copilot)
- Guard tau() against non-positive total_area; include the element kind in
finite-check error labels. (gemini/Copilot)
- Docstring: bands accepts 'third-octave' (not 'third'). (Copilot)
- Tests for all of the above.
* docs: address CodeRabbit review on facade prediction docs
- Fix worked-example prose: the snippet has a window + a skylight, not
'two windows' (docs + EN/ES site guides).
- Complete the façade parameter table with facade_sound_reduction(frequencies),
radiated_sound_power(octave_bands) and outdoor_level() rows (docs + EN/ES).
- Document the optional 'frequencies' parameter in the facade_sound_reduction
API-reference rows (docs + EN/ES).
- Regenerate llms-full.txt.
The Major duplicate-name finding was already fixed in af23efc.
feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000) (#125)
* feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000)
New module phonometry.facade_prediction implementing the two building-envelope
prediction directions on a shared energy summation of element transmission
factors:
- EN 12354-3 (outdoor -> indoor): facade_sound_reduction() -> apparent R'
(Formula 10), the loudspeaker/traffic indices R45/Rtr,s (11/12) and the
standardized level difference D2m,nT (13), with ISO 717-1 single numbers.
- EN 12354-4 (indoor -> outdoor): radiated_sound_power() -> segment R' and the
radiated power level LW (Formula 2), plus the simplified Annex E outdoor
attenuation (outdoor_attenuation / outdoor_level).
FacadeElement models an area element (R), a small element / air path (Dn,e) or
an opening (insertion loss); FacadePredictionResult and RadiatedPowerResult are
frozen dataclasses exposing .plot().
Validated clean-room against the Part 3 Annex F and Part 4 Annex G worked
examples: the low octave bands, every single-number rating and the whole Annex E
propagation reproduce the published values exactly (3 new conformance checks,
98/98). The standards' own worked examples carry documented internal rounding
inconsistencies at the higher bands, tracked in the reference-data notes.
Adds the EN/ES facade_prediction figure (SVG, deterministic), the EN 12354-3/-4
section in the building-acoustics guide (EN + ES site), API-reference rows and
regenerated CONFORMANCE.md / llms-full.txt.
* fix: avoid assert for type-narrowing in FacadeElement.tau (bandit B101)
The rest of src/ avoids assert (removed under python -O); fetch the single
non-None quantity via getattr, matching the _band_count pattern, so mypy is
satisfied without an assert.
* review: harden facade_prediction per bot review
- Fix a real bug: _apparent_reduction keyed transmission factors by element
name in a dict, so two elements sharing a name silently dropped one from the
R' sum. Sum over the element list and require unique names (they key the
per-element result). (gemini)
- outdoor_level: allow NumPy broadcasting (scalar Atot vs per-side LW array).
- Validate 'frequencies' / 'octave_bands' length against the band count. (Copilot)
- Guard tau() against non-positive total_area; include the element kind in
finite-check error labels. (gemini/Copilot)
- Docstring: bands accepts 'third-octave' (not 'third'). (Copilot)
- Tests for all of the above.
* docs: address CodeRabbit review on facade prediction docs
- Fix worked-example prose: the snippet has a window + a skylight, not
'two windows' (docs + EN/ES site guides).
- Complete the façade parameter table with facade_sound_reduction(frequencies),
radiated_sound_power(octave_bands) and outdoor_level() rows (docs + EN/ES).
- Document the optional 'frequencies' parameter in the facade_sound_reduction
API-reference rows (docs + EN/ES).
- Regenerate llms-full.txt.
The Major duplicate-name finding was already fixed in af23efc.
feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000) (#125)
* feat: façade insulation & outdoor radiation prediction (EN 12354-3/-4:2000)
New module phonometry.facade_prediction implementing the two building-envelope
prediction directions on a shared energy summation of element transmission
factors:
- EN 12354-3 (outdoor -> indoor): facade_sound_reduction() -> apparent R'
(Formula 10), the loudspeaker/traffic indices R45/Rtr,s (11/12) and the
standardized level difference D2m,nT (13), with ISO 717-1 single numbers.
- EN 12354-4 (indoor -> outdoor): radiated_sound_power() -> segment R' and the
radiated power level LW (Formula 2), plus the simplified Annex E outdoor
attenuation (outdoor_attenuation / outdoor_level).
FacadeElement models an area element (R), a small element / air path (Dn,e) or
an opening (insertion loss); FacadePredictionResult and RadiatedPowerResult are
frozen dataclasses exposing .plot().
Validated clean-room against the Part 3 Annex F and Part 4 Annex G worked
examples: the low octave bands, every single-number rating and the whole Annex E
propagation reproduce the published values exactly (3 new conformance checks,
98/98). The standards' own worked examples carry documented internal rounding
inconsistencies at the higher bands, tracked in the reference-data notes.
Adds the EN/ES facade_prediction figure (SVG, deterministic), the EN 12354-3/-4
section in the building-acoustics guide (EN + ES site), API-reference rows and
regenerated CONFORMANCE.md / llms-full.txt.
* fix: avoid assert for type-narrowing in FacadeElement.tau (bandit B101)
The rest of src/ avoids assert (removed under python -O); fetch the single
non-None quantity via getattr, matching the _band_count pattern, so mypy is
satisfied without an assert.
* review: harden facade_prediction per bot review
- Fix a real bug: _apparent_reduction keyed transmission factors by element
name in a dict, so two elements sharing a name silently dropped one from the
R' sum. Sum over the element list and require unique names (they key the
per-element result). (gemini)
- outdoor_level: allow NumPy broadcasting (scalar Atot vs per-side LW array).
- Validate 'frequencies' / 'octave_bands' length against the band count. (Copilot)
- Guard tau() against non-positive total_area; include the element kind in
finite-check error labels. (gemini/Copilot)
- Docstring: bands accepts 'third-octave' (not 'third'). (Copilot)
- Tests for all of the above.
* docs: address CodeRabbit review on facade prediction docs
- Fix worked-example prose: the snippet has a window + a skylight, not
'two windows' (docs + EN/ES site guides).
- Complete the façade parameter table with facade_sound_reduction(frequencies),
radiated_sound_power(octave_bands) and outdoor_level() rows (docs + EN/ES).
- Document the optional 'frequencies' parameter in the facade_sound_reduction
API-reference rows (docs + EN/ES).
- Regenerate llms-full.txt.
The Major duplicate-name finding was already fixed in af23efc.
feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification (#126)
* feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification
verify_filter_class and class_limits gain an `edition` argument. The default
"2014" path (IEC 61260-1:2014, classes 1 and 2) is unchanged; edition "1995"
selects the withdrawn IEC 61260:1995 / ANSI S1.11-2004 Table 1, which adds the
stricter laboratory-grade class 0 and whose class 1/2 masks differ slightly
from the 2014 edition.
The 1995/ANSI octave-band Table 1 was transcribed digit-for-digit and verified
identical between the two standards (dual-oracle clean-room). The fractional-
octave breakpoint mapping is shared: 1995 Annex B equation (10) is identical to
2014 Formula (9), so the existing _map_breakpoint is reused for both editions.
The library default (Butterworth order 6) already meets class 0 across the usual
configurations (octave/third-octave, 32-96 kHz); the non-Butterworth
architectures cannot reach the class mask by construction (ripple / flat group
delay), so defaults are unchanged and the class each architecture reaches is
documented instead.
Adds a class-0 conformance check (99/99), the EN/ES filter_class0_mask figure,
tests cross-checked against a shared reference_data copy, the "Class 0" doc
section (guide EN/ES + API refs EN/ES) and regenerated CONFORMANCE.md /
llms-full.txt.
* docs: address bot review — scope class-0 claims, fix English decimals
- compliance.py: English docstring tolerances use dot decimals and ± symbol
(were decimal commas, inconsistent in an English context).
- api-reference (docs + site EN/ES): qualify overall_class by edition
(1/2/None for "2014"; 0/1/2/None for "1995"); neutralize the ES headers that
still said "IEC 61260-1:2014" while documenting the edition switch.
- filter-banks (docs + site EN/ES): narrow the class-0 wording to the verified
order-6 Butterworth octave/third-octave banks at 48 kHz; drop the untested
32-96 kHz range and advise re-running verify_filter_class away from those
settings.
- generate_graphs.py: fix misleading "filter_class0_mask.png" print (output is
SVG).
- test_compliance.py: assert the class-0/1/2 minimum ordering the docstring
already promised (previously only the maximum ordering was checked).
feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification (#126)
* feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification
verify_filter_class and class_limits gain an `edition` argument. The default
"2014" path (IEC 61260-1:2014, classes 1 and 2) is unchanged; edition "1995"
selects the withdrawn IEC 61260:1995 / ANSI S1.11-2004 Table 1, which adds the
stricter laboratory-grade class 0 and whose class 1/2 masks differ slightly
from the 2014 edition.
The 1995/ANSI octave-band Table 1 was transcribed digit-for-digit and verified
identical between the two standards (dual-oracle clean-room). The fractional-
octave breakpoint mapping is shared: 1995 Annex B equation (10) is identical to
2014 Formula (9), so the existing _map_breakpoint is reused for both editions.
The library default (Butterworth order 6) already meets class 0 across the usual
configurations (octave/third-octave, 32-96 kHz); the non-Butterworth
architectures cannot reach the class mask by construction (ripple / flat group
delay), so defaults are unchanged and the class each architecture reaches is
documented instead.
Adds a class-0 conformance check (99/99), the EN/ES filter_class0_mask figure,
tests cross-checked against a shared reference_data copy, the "Class 0" doc
section (guide EN/ES + API refs EN/ES) and regenerated CONFORMANCE.md /
llms-full.txt.
* docs: address bot review — scope class-0 claims, fix English decimals
- compliance.py: English docstring tolerances use dot decimals and ± symbol
(were decimal commas, inconsistent in an English context).
- api-reference (docs + site EN/ES): qualify overall_class by edition
(1/2/None for "2014"; 0/1/2/None for "1995"); neutralize the ES headers that
still said "IEC 61260-1:2014" while documenting the edition switch.
- filter-banks (docs + site EN/ES): narrow the class-0 wording to the verified
order-6 Butterworth octave/third-octave banks at 48 kHz; drop the untested
32-96 kHz range and advise re-running verify_filter_class away from those
settings.
- generate_graphs.py: fix misleading "filter_class0_mask.png" print (output is
SVG).
- test_compliance.py: assert the class-0/1/2 minimum ordering the docstring
already promised (previously only the maximum ordering was checked).
feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification (#126)
* feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification
verify_filter_class and class_limits gain an `edition` argument. The default
"2014" path (IEC 61260-1:2014, classes 1 and 2) is unchanged; edition "1995"
selects the withdrawn IEC 61260:1995 / ANSI S1.11-2004 Table 1, which adds the
stricter laboratory-grade class 0 and whose class 1/2 masks differ slightly
from the 2014 edition.
The 1995/ANSI octave-band Table 1 was transcribed digit-for-digit and verified
identical between the two standards (dual-oracle clean-room). The fractional-
octave breakpoint mapping is shared: 1995 Annex B equation (10) is identical to
2014 Formula (9), so the existing _map_breakpoint is reused for both editions.
The library default (Butterworth order 6) already meets class 0 across the usual
configurations (octave/third-octave, 32-96 kHz); the non-Butterworth
architectures cannot reach the class mask by construction (ripple / flat group
delay), so defaults are unchanged and the class each architecture reaches is
documented instead.
Adds a class-0 conformance check (99/99), the EN/ES filter_class0_mask figure,
tests cross-checked against a shared reference_data copy, the "Class 0" doc
section (guide EN/ES + API refs EN/ES) and regenerated CONFORMANCE.md /
llms-full.txt.
* docs: address bot review — scope class-0 claims, fix English decimals
- compliance.py: English docstring tolerances use dot decimals and ± symbol
(were decimal commas, inconsistent in an English context).
- api-reference (docs + site EN/ES): qualify overall_class by edition
(1/2/None for "2014"; 0/1/2/None for "1995"); neutralize the ES headers that
still said "IEC 61260-1:2014" while documenting the edition switch.
- filter-banks (docs + site EN/ES): narrow the class-0 wording to the verified
order-6 Butterworth octave/third-octave banks at 48 kHz; drop the untested
32-96 kHz range and advise re-running verify_filter_class away from those
settings.
- generate_graphs.py: fix misleading "filter_class0_mask.png" print (output is
SVG).
- test_compliance.py: assert the class-0/1/2 minimum ordering the docstring
already promised (previously only the maximum ordering was checked).
feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification (#126)
* feat: IEC 61260:1995 / ANSI S1.11-2004 class 0 filter verification
verify_filter_class and class_limits gain an `edition` argument. The default
"2014" path (IEC 61260-1:2014, classes 1 and 2) is unchanged; edition "1995"
selects the withdrawn IEC 61260:1995 / ANSI S1.11-2004 Table 1, which adds the
stricter laboratory-grade class 0 and whose class 1/2 masks differ slightly
from the 2014 edition.
The 1995/ANSI octave-band Table 1 was transcribed digit-for-digit and verified
identical between the two standards (dual-oracle clean-room). The fractional-
octave breakpoint mapping is shared: 1995 Annex B equation (10) is identical to
2014 Formula (9), so the existing _map_breakpoint is reused for both editions.
The library default (Butterworth order 6) already meets class 0 across the usual
configurations (octave/third-octave, 32-96 kHz); the non-Butterworth
architectures cannot reach the class mask by construction (ripple / flat group
delay), so defaults are unchanged and the class each architecture reaches is
documented instead.
Adds a class-0 conformance check (99/99), the EN/ES filter_class0_mask figure,
tests cross-checked against a shared reference_data copy, the "Class 0" doc
section (guide EN/ES + API refs EN/ES) and regenerated CONFORMANCE.md /
llms-full.txt.
* docs: address bot review — scope class-0 claims, fix English decimals
- compliance.py: English docstring tolerances use dot decimals and ± symbol
(were decimal commas, inconsistent in an English context).
- api-reference (docs + site EN/ES): qualify overall_class by edition
(1/2/None for "2014"; 0/1/2/None for "1995"); neutralize the ES headers that
still said "IEC 61260-1:2014" while documenting the edition switch.
- filter-banks (docs + site EN/ES): narrow the class-0 wording to the verified
order-6 Butterworth octave/third-octave banks at 48 kHz; drop the untested
32-96 kHz range and advise re-running verify_filter_class away from those
settings.
- generate_graphs.py: fix misleading "filter_class0_mask.png" print (output is
SVG).
- test_compliance.py: assert the class-0/1/2 minimum ordering the docstring
already promised (previously only the maximum ordering was checked).
feat: floor-covering impact improvement on a mock-up (ISO 16251-1:2014) (#130)
Add the laboratory method for the improvement of impact sound insulation ΔL of
soft, locally-reacting floor coverings (carpet, PVC, linoleum) measured on a
small concrete mock-up via structure-borne acceleration levels, plus the
ISO 717-2 weighted improvement ΔLw it feeds.
- weighted_impact_improvement (insulation.py): ISO 717-2:2020 Clause 5 ΔLw =
78 - Ln,r,w using the heavyweight reference floor of Table 4, reusing the
verified weighted_impact_rating engine
- floor_covering_improvement.py (ISO 16251-1):
- acceleration_level (Formula 1, a0 = 1e-6 m/s²)
- background_corrected_level (Formula 2, three-branch rule with a
limit-of-measurement flag)
- impact_improvement: Formula (2) per position -> difference (3) -> mean over
positions (4); accepts (bands,) or (positions, bands) levels
- improvement_octave_bands (Formula 5)
- FloorCoveringImprovementResult with ΔLw, the > ΔL limit mask and .plot()
- Conformance checks: ISO 717-2 reference-floor rating (78 dB, CI -11) and the
ΔL=0 -> ΔLw=0 identity (109/109). ISO 16251-1 has no worked numeric example
(Annex B is a blank form), so the oracle is the ISO 717-2 reference floor.
- generate_floor_covering_improvement figure (EN/ES × light/dark)
- Building-acoustics guide §7 and API reference rows (EN + ES)
- 20 tests covering all formulas, the per-position ordering and validation
feat: floor-covering impact improvement on a mock-up (ISO 16251-1:2014) (#130)
Add the laboratory method for the improvement of impact sound insulation ΔL of
soft, locally-reacting floor coverings (carpet, PVC, linoleum) measured on a
small concrete mock-up via structure-borne acceleration levels, plus the
ISO 717-2 weighted improvement ΔLw it feeds.
- weighted_impact_improvement (insulation.py): ISO 717-2:2020 Clause 5 ΔLw =
78 - Ln,r,w using the heavyweight reference floor of Table 4, reusing the
verified weighted_impact_rating engine
- floor_covering_improvement.py (ISO 16251-1):
- acceleration_level (Formula 1, a0 = 1e-6 m/s²)
- background_corrected_level (Formula 2, three-branch rule with a
limit-of-measurement flag)
- impact_improvement: Formula (2) per position -> difference (3) -> mean over
positions (4); accepts (bands,) or (positions, bands) levels
- improvement_octave_bands (Formula 5)
- FloorCoveringImprovementResult with ΔLw, the > ΔL limit mask and .plot()
- Conformance checks: ISO 717-2 reference-floor rating (78 dB, CI -11) and the
ΔL=0 -> ΔLw=0 identity (109/109). ISO 16251-1 has no worked numeric example
(Annex B is a blank form), so the oracle is the ISO 717-2 reference floor.
- generate_floor_covering_improvement figure (EN/ES × light/dark)
- Building-acoustics guide §7 and API reference rows (EN + ES)
- 20 tests covering all formulas, the per-position ordering and validation
feat: floor-covering impact improvement on a mock-up (ISO 16251-1:2014) (#130)
Add the laboratory method for the improvement of impact sound insulation ΔL of
soft, locally-reacting floor coverings (carpet, PVC, linoleum) measured on a
small concrete mock-up via structure-borne acceleration levels, plus the
ISO 717-2 weighted improvement ΔLw it feeds.
- weighted_impact_improvement (insulation.py): ISO 717-2:2020 Clause 5 ΔLw =
78 - Ln,r,w using the heavyweight reference floor of Table 4, reusing the
verified weighted_impact_rating engine
- floor_covering_improvement.py (ISO 16251-1):
- acceleration_level (Formula 1, a0 = 1e-6 m/s²)
- background_corrected_level (Formula 2, three-branch rule with a
limit-of-measurement flag)
- impact_improvement: Formula (2) per position -> difference (3) -> mean over
positions (4); accepts (bands,) or (positions, bands) levels
- improvement_octave_bands (Formula 5)
- FloorCoveringImprovementResult with ΔLw, the > ΔL limit mask and .plot()
- Conformance checks: ISO 717-2 reference-floor rating (78 dB, CI -11) and the
ΔL=0 -> ΔLw=0 identity (109/109). ISO 16251-1 has no worked numeric example
(Annex B is a blank form), so the oracle is the ISO 717-2 reference floor.
- generate_floor_covering_improvement figure (EN/ES × light/dark)
- Building-acoustics guide §7 and API reference rows (EN + ES)
- 20 tests covering all formulas, the per-position ordering and validation
feat: floor-covering impact improvement on a mock-up (ISO 16251-1:2014) (#130)
Add the laboratory method for the improvement of impact sound insulation ΔL of
soft, locally-reacting floor coverings (carpet, PVC, linoleum) measured on a
small concrete mock-up via structure-borne acceleration levels, plus the
ISO 717-2 weighted improvement ΔLw it feeds.
- weighted_impact_improvement (insulation.py): ISO 717-2:2020 Clause 5 ΔLw =
78 - Ln,r,w using the heavyweight reference floor of Table 4, reusing the
verified weighted_impact_rating engine
- floor_covering_improvement.py (ISO 16251-1):
- acceleration_level (Formula 1, a0 = 1e-6 m/s²)
- background_corrected_level (Formula 2, three-branch rule with a
limit-of-measurement flag)
- impact_improvement: Formula (2) per position -> difference (3) -> mean over
positions (4); accepts (bands,) or (positions, bands) levels
- improvement_octave_bands (Formula 5)
- FloorCoveringImprovementResult with ΔLw, the > ΔL limit mask and .plot()
- Conformance checks: ISO 717-2 reference-floor rating (78 dB, CI -11) and the
ΔL=0 -> ΔLw=0 identity (109/109). ISO 16251-1 has no worked numeric example
(Annex B is a blank form), so the oracle is the ISO 717-2 reference floor.
- generate_floor_covering_improvement figure (EN/ES × light/dark)
- Building-acoustics guide §7 and API reference rows (EN + ES)
- 20 tests covering all formulas, the per-position ordering and validation
feat: sound insulation by intensity (ISO 15186-1:2000) (#127)
* feat: sound insulation by intensity (ISO 15186-1:2000)
Adds the sound-intensity method as the direct-power counterpart to the
ISO 10140 laboratory pressure method — the tool of choice when flanking
transmission defeats the traditional method.
New module `intensity_insulation.py`:
- `intensity_sound_reduction` — intensity sound reduction index
RI = Lp1 - 6 - [LIn + 10 lg(Sm/S)] (Formula (7)); also the field apparent
R'I (ISO 15186-2) and the Kc-modified RI,M = RI + Kc (Formula (9)).
- `adaptation_term_kc` — Annex B term: exact Formula (B.1)
10 lg(1 + Sb2·λ/8V2) for a well-defined room, or the room-independent
approximation (B.2) 10 lg(1 + 61,4/f); both with c = 340 m/s so (B.1) with
the reference room reduces to (B.2).
- `intensity_element_normalized_difference` — DI,n,e (Formula (8)).
- `surface_pressure_intensity_indicator` — FpI qualification (Formula (10)).
- `combine_subareas` — per-subarea energy average (Formulas (11)-(12)).
Weighted ratings (RI,w, RI,M,w, DI,n,e,w) reuse the verified ISO 717-1
`weighted_rating` engine; result objects mirror `lab_insulation.py`
(frozen dataclasses, `.plot()` delegating to the rating).
Adds 19 tests, two conformance checks (RI reproduces the ISO 717-1 Rw=30
through the intensity path; Annex B B.1 reduces to B.2), the deterministic
`intensity_insulation` figure (EN/ES × light/dark), and a §5 in the
building-acoustics guide (docs + site EN/ES) plus API-reference rows.
* Address bot review — ES figure localisation, nominal centres, table escaping
- generate_graphs.py: the intensity_insulation info box is now data-only
(RI,w / RI,M,w), so the untranslatable multiline annotation is gone; add an
_ES_EXACT entry for the "RI (intensity)" legend label. Regenerated the four
deterministic SVG variants — the ES figure is now fully localised.
- docs + site EN/ES: the RI,M example uses the nominal one-third-octave centres
(100-3150 Hz) instead of np.geomspace, matching the "1/3-octave bands" claim;
printed values are unchanged. Same in the test.
- conformance_report.py: the Annex B check message uses abs(B.1 - B.2) instead
of |B.1 - B.2| so the pipes no longer break the CONFORMANCE.md table row;
regenerated the report.
- intensity_insulation.py: restructure adaptation_term_kc's branch so mypy
narrows both room parameters, dropping the type: ignore.
feat: sound insulation by intensity (ISO 15186-1:2000) (#127)
* feat: sound insulation by intensity (ISO 15186-1:2000)
Adds the sound-intensity method as the direct-power counterpart to the
ISO 10140 laboratory pressure method — the tool of choice when flanking
transmission defeats the traditional method.
New module `intensity_insulation.py`:
- `intensity_sound_reduction` — intensity sound reduction index
RI = Lp1 - 6 - [LIn + 10 lg(Sm/S)] (Formula (7)); also the field apparent
R'I (ISO 15186-2) and the Kc-modified RI,M = RI + Kc (Formula (9)).
- `adaptation_term_kc` — Annex B term: exact Formula (B.1)
10 lg(1 + Sb2·λ/8V2) for a well-defined room, or the room-independent
approximation (B.2) 10 lg(1 + 61,4/f); both with c = 340 m/s so (B.1) with
the reference room reduces to (B.2).
- `intensity_element_normalized_difference` — DI,n,e (Formula (8)).
- `surface_pressure_intensity_indicator` — FpI qualification (Formula (10)).
- `combine_subareas` — per-subarea energy average (Formulas (11)-(12)).
Weighted ratings (RI,w, RI,M,w, DI,n,e,w) reuse the verified ISO 717-1
`weighted_rating` engine; result objects mirror `lab_insulation.py`
(frozen dataclasses, `.plot()` delegating to the rating).
Adds 19 tests, two conformance checks (RI reproduces the ISO 717-1 Rw=30
through the intensity path; Annex B B.1 reduces to B.2), the deterministic
`intensity_insulation` figure (EN/ES × light/dark), and a §5 in the
building-acoustics guide (docs + site EN/ES) plus API-reference rows.
* Address bot review — ES figure localisation, nominal centres, table escaping
- generate_graphs.py: the intensity_insulation info box is now data-only
(RI,w / RI,M,w), so the untranslatable multiline annotation is gone; add an
_ES_EXACT entry for the "RI (intensity)" legend label. Regenerated the four
deterministic SVG variants — the ES figure is now fully localised.
- docs + site EN/ES: the RI,M example uses the nominal one-third-octave centres
(100-3150 Hz) instead of np.geomspace, matching the "1/3-octave bands" claim;
printed values are unchanged. Same in the test.
- conformance_report.py: the Annex B check message uses abs(B.1 - B.2) instead
of |B.1 - B.2| so the pipes no longer break the CONFORMANCE.md table row;
regenerated the report.
- intensity_insulation.py: restructure adaptation_term_kc's branch so mypy
narrows both room parameters, dropping the type: ignore.
feat: sound insulation by intensity (ISO 15186-1:2000) (#127)
* feat: sound insulation by intensity (ISO 15186-1:2000)
Adds the sound-intensity method as the direct-power counterpart to the
ISO 10140 laboratory pressure method — the tool of choice when flanking
transmission defeats the traditional method.
New module `intensity_insulation.py`:
- `intensity_sound_reduction` — intensity sound reduction index
RI = Lp1 - 6 - [LIn + 10 lg(Sm/S)] (Formula (7)); also the field apparent
R'I (ISO 15186-2) and the Kc-modified RI,M = RI + Kc (Formula (9)).
- `adaptation_term_kc` — Annex B term: exact Formula (B.1)
10 lg(1 + Sb2·λ/8V2) for a well-defined room, or the room-independent
approximation (B.2) 10 lg(1 + 61,4/f); both with c = 340 m/s so (B.1) with
the reference room reduces to (B.2).
- `intensity_element_normalized_difference` — DI,n,e (Formula (8)).
- `surface_pressure_intensity_indicator` — FpI qualification (Formula (10)).
- `combine_subareas` — per-subarea energy average (Formulas (11)-(12)).
Weighted ratings (RI,w, RI,M,w, DI,n,e,w) reuse the verified ISO 717-1
`weighted_rating` engine; result objects mirror `lab_insulation.py`
(frozen dataclasses, `.plot()` delegating to the rating).
Adds 19 tests, two conformance checks (RI reproduces the ISO 717-1 Rw=30
through the intensity path; Annex B B.1 reduces to B.2), the deterministic
`intensity_insulation` figure (EN/ES × light/dark), and a §5 in the
building-acoustics guide (docs + site EN/ES) plus API-reference rows.
* Address bot review — ES figure localisation, nominal centres, table escaping
- generate_graphs.py: the intensity_insulation info box is now data-only
(RI,w / RI,M,w), so the untranslatable multiline annotation is gone; add an
_ES_EXACT entry for the "RI (intensity)" legend label. Regenerated the four
deterministic SVG variants — the ES figure is now fully localised.
- docs + site EN/ES: the RI,M example uses the nominal one-third-octave centres
(100-3150 Hz) instead of np.geomspace, matching the "1/3-octave bands" claim;
printed values are unchanged. Same in the test.
- conformance_report.py: the Annex B check message uses abs(B.1 - B.2) instead
of |B.1 - B.2| so the pipes no longer break the CONFORMANCE.md table row;
regenerated the report.
- intensity_insulation.py: restructure adaptation_term_kc's branch so mypy
narrows both room parameters, dropping the type: ignore.
feat: sound insulation by intensity (ISO 15186-1:2000) (#127)
* feat: sound insulation by intensity (ISO 15186-1:2000)
Adds the sound-intensity method as the direct-power counterpart to the
ISO 10140 laboratory pressure method — the tool of choice when flanking
transmission defeats the traditional method.
New module `intensity_insulation.py`:
- `intensity_sound_reduction` — intensity sound reduction index
RI = Lp1 - 6 - [LIn + 10 lg(Sm/S)] (Formula (7)); also the field apparent
R'I (ISO 15186-2) and the Kc-modified RI,M = RI + Kc (Formula (9)).
- `adaptation_term_kc` — Annex B term: exact Formula (B.1)
10 lg(1 + Sb2·λ/8V2) for a well-defined room, or the room-independent
approximation (B.2) 10 lg(1 + 61,4/f); both with c = 340 m/s so (B.1) with
the reference room reduces to (B.2).
- `intensity_element_normalized_difference` — DI,n,e (Formula (8)).
- `surface_pressure_intensity_indicator` — FpI qualification (Formula (10)).
- `combine_subareas` — per-subarea energy average (Formulas (11)-(12)).
Weighted ratings (RI,w, RI,M,w, DI,n,e,w) reuse the verified ISO 717-1
`weighted_rating` engine; result objects mirror `lab_insulation.py`
(frozen dataclasses, `.plot()` delegating to the rating).
Adds 19 tests, two conformance checks (RI reproduces the ISO 717-1 Rw=30
through the intensity path; Annex B B.1 reduces to B.2), the deterministic
`intensity_insulation` figure (EN/ES × light/dark), and a §5 in the
building-acoustics guide (docs + site EN/ES) plus API-reference rows.
* Address bot review — ES figure localisation, nominal centres, table escaping
- generate_graphs.py: the intensity_insulation info box is now data-only
(RI,w / RI,M,w), so the untranslatable multiline annotation is gone; add an
_ES_EXACT entry for the "RI (intensity)" legend label. Regenerated the four
deterministic SVG variants — the ES figure is now fully localised.
- docs + site EN/ES: the RI,M example uses the nominal one-third-octave centres
(100-3150 Hz) instead of np.geomspace, matching the "1/3-octave bands" claim;
printed values are unchanged. Same in the test.
- conformance_report.py: the Annex B check message uses abs(B.1 - B.2) instead
of |B.1 - B.2| so the pipes no longer break the CONFORMANCE.md table row;
regenerated the report.
- intensity_insulation.py: restructure adaptation_term_kc's branch so mypy
narrows both room parameters, dropping the type: ignore.
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
Sound power determination and building acoustics II: ISO 3744/3746, ISO 3741, ISO 9614-2, ISO 16283-2 + ISO 717-2, ISO 354 (#84)
* feat: ISO 3744/3746 sound power from pressure measurements
Add sound_power.py: sound power level of a noise source from sound
pressure levels over an enveloping measurement surface, ISO 3744:2010
(engineering, grade 2) and ISO 3746:2010 (survey, grade 3).
- sound_power_pressure(): per-band LW and A-weighted LWA from an
(NM, NB) level array over a hemisphere (radius) or parallelepiped
(dimensions + distance); surface area from the standard's closed forms
for 1/2/3 reflecting planes; energy average (Eq. 12), background K1
(Eq. 16), environmental K2 (Eq. A.2), apparent directivity index
(Eq. 7), expanded uncertainty.
- measurement_positions(): normative Annex B coordinates
(Tables B.1/B.2/B.3), grade- and plane-dependent subsets.
- background_noise_correction(): K1 with engineering/survey criteria.
- environmental_correction(): K2 from A, Sabine T+V, or alpha*Sv.
- SoundPowerResult (frozen dataclass), SoundPowerWarning.
Tests: 24 cases incl. monopole-over-plane exact LW recovery, radius
independence, K1/K2 closed forms, LWA via Annex E, and validations.
make check green (543 passed, 12 skipped); ruff/bandit/mypy --strict clean.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: directivity index under background correction, citation hygiene
Broadband K1 for the apparent directivity index was collapsing to the
surface-area term 10*lg(S/S0) (~+22 dB inflation with background
correction). Compute the true energy-based broadband K1 (per-band Eq. 16
aggregated over bands) so DI is correct in both paths.
Also: multi-band sound_power_level_a without frequencies now returns NaN
(A-weighting needs band centres); dropped PDF page-number citations from
Annex B/E table comments; corrected the survey parallelepiped position
citation to ISO 3746 clause C.1 / Figure C.7.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 3741 reverberation-room sound power
Add the ISO 3741:2010 precision (grade 1) methods for determining sound
power in a reverberation test room, in a new sound_power_reverberation
module:
- sound_power_reverberation() — direct method (Eq. 20): LW from the mean
room SPL and the Sabine equivalent absorption area A = (55,26/c)(V/T60),
with the full normative bracket: 10 lg(A/A0), 4,34*(A/S), the Waterhouse
boundary term 10 lg(1 + S c/(8 V f)), the reference-quantity (C1) and
radiation-impedance (C2) meteorological corrections and the -6 dB
constant. Speed of sound c = 20,05*sqrt(273 + theta).
- sound_power_comparison() — comparison method (Eq. 21) with a reference
sound source: LW = LW(RSS) + (Lp(ST) - Lp(RSS) + C2).
- ReverberationSoundPowerResult frozen dataclass; frequency-dependent
background correction K1 (Eq. 14, same formula as ISO 3744) with the
precision-grade 6/10 dB criteria; A-weighted total via Annex F.
Reuses the ISO 3744 energy-average and A-weighting helpers. Tests cover
exact inversion of Eq. (20), the Waterhouse term vanishing at high
frequency, the comparison method exact by construction, and synergy with
room_parameters T30 feeding the direct method.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 3741 room-qualification advisories and validation ordering
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 9614-2 sound power by intensity scanning
Add sound_power_intensity() computing per-band LW = 10lg(sum Pi/P0) from
per-segment signed normal intensity and areas (partial power Pi = <In,i>*Si),
the scanning-method field indicators FpI (Eq. A.1) and F+/- (Eq. A.2), the
repeatability criterion 3, and the achieved engineering/survey grade per band
(Annex B criteria 1-3). Negative total power flags bands as non-determinable
(clause 9.2); negative partial power raises SoundPowerWarning. Reuses
dynamic_capability_index for Ld = dpI0 - K (Table 1).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 16283-2 impact sound insulation and ISO 717-2 ratings
Add field impact sound insulation (ISO 16283-2, tapping machine) and the
ISO 717-2 single-number weighted impact rating with the CI spectrum
adaptation term, reusing the verified reference-curve shift engine.
- impact_insulation(li, t2, *, volume=None, t0=0.5): per-band
L'nT = Li - 10 lg(T/T0) (Formula (1)) and L'n = Li + 10 lg(A/A0) with
A = 0,16 V/T, A0 = 10 m2 (Formula (2)); positions energy-averaged.
- weighted_impact_rating(values_by_band, bands=None): Ln,w / L'n,w /
L'nT,w (Clause 4.3, octave -5 dB rule) and CI (Clause A.2.1, energetic
sum 100-2500 / 125-2000). Impact unfavourable deviations (measurement
exceeds reference, sign opposite to airborne) reduce to the airborne
search on negated curves, so _best_shift is reused verbatim.
- _best_shift: tolerance absorbs float noise at the exact bound (sums are
true multiples of 0,1 dB); airborne behaviour unchanged.
Verified against ISO 717-2 Annex C worked examples (Table C.1 Ln,w=79,
CI=-11; Table C.3 octave Ln,w=54, CI=0) and an independent brute-force
shift search on 10 000 random curves per band set. 2013 and 2020 editions
are identical for all implemented maths (2020 only adds Annex D rubber
ball, out of scope).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* feat: ISO 354 sound absorption in a reverberation room
Add phonometry.sound_absorption implementing BS EN ISO 354:2003:
- absorption_area(t60, volume, ...): equivalent sound absorption area
A = 55,3*V/(c*T) - 4*V*m (Eq. 5/7), speed of sound from Eq. (6).
- absorption_coefficient(t1, t2, volume, sample_area, ...): alpha_s =
(A2-A1)/S built from Eq. (8)/(9), per-measurement c1/c2, unclamped
(alpha_s > 1 valid, clause 3.7 NOTE 2); warns when T2 >= T1.
- attenuation_from_alpha: ISO-354 conversion m = alpha/(10 lg e) from an
ISO 9613-1 attenuation coefficient (m deferred to ISO 9613-1, default 0).
Composes directly with room_parameters() T20/T30 outputs. 25 tests
(exact T->A->T inversion, synthetic-alpha recovery, zero-m air term,
two-temperature Eq. (8), range validation, room_parameters synergy).
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: ISO 354 room and sample-size advisories
Add advisory AbsorptionWarning (never raising; result still returned) for
setup conditions outside ISO 354:2003 limits:
- Room volume below the 150 m3 minimum of clause 6.1.1, in both
absorption_area and absorption_coefficient.
- Sample area outside the clause 6.2.1.1 range 10 <= S <= 12 m2, with the
upper limit scaled by (V/200)^(2/3) when V > 200 m3, in
absorption_coefficient.
The volume advisory is emitted once by absorption_coefficient and suppressed
in its internal absorption_area calls to avoid duplicate warnings.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: deferred review minors — airborne brute-force net, advisory consistency, labels
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound power guide, impact and absorption sections, theory and API (EN)
Add a "Sound Power" guide covering the three LW routes (ISO 3744/3746
enveloping surface, ISO 3741 reverberation room with Waterhouse/C1/C2,
ISO 9614-2 intensity scanning), with a method-comparison table, executed
snippets and parameter tables. Extend the Room & Building Acoustics guide
with impact sound insulation (ISO 16283-2 + ISO 717-2, L'nT/L'n, tapping
machine, CI) and sound absorption in a reverberation room (ISO 354).
Add the matching theory sections (K1/K2, Waterhouse, C1/C2 derivations;
impact sign conventions; Sabine absorption) and API-reference rows for all
new public names. Update the landing standards count to 26, the sidebar,
README highlights/table, CHANGELOG and llms-full.txt.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: sound-power and impact figures and diagrams
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: include the sound-power guide in llms coverage
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: reposition Ln,w annotation in the impact figure
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* docs: gemelas ES de potencia sonora, impacto y absorción
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: final-review findings — comparison K1 reporting, citations, knee unification, docs attribution
- sound_power_comparison now reports the test-source K1 actually applied
per band (zero when no background), matching the dataclass docstring;
LW unchanged.
- Replace gitignored notes-iso3744-3746.md citation in the DI comment with
the standard reference (ISO 3744:2010, 3.24 / Eq. 7 context).
- Unify the K1 zeroing knee to the >= form (ΔLp >= 15 -> no correction).
- Broaden SoundPowerWarning docstring to name all emitters (ISO 3744/3746,
ISO 3741, ISO 9614-2).
- Fix docs misattributing K2 to ISO 3741 (ISO 3744 K2 vs ISO 3741 absorption
term) across EN/ES room-acoustics guides.
- EN impact-setup diagram uses dot decimals (0.16); regenerate the 4 variants.
- CHANGELOG: label the ISO 717-2 Annex C value Ln,w = 79.
- Warn-after-validate in sound_power_comparison; "is raised" -> "is emitted".
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 review round 1 — per-band DI and K2, sweep-reversal repeatability, validation and broadcast ergonomics
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
* fix: PR 84 round 2 — partial room-data validation, result-field docs
Raise a clear ValueError in environmental_correction (and its
sound_power_pressure pass-through) when exactly one member of a
room-data pair (reverberation_time/room_volume or
mean_absorption_coefficient/room_surface) is supplied, instead of
silently returning K2=0 as if free field. All-None remains the
legitimate free-field K2=0 path.
Document frequencies on the ReverberationSoundPowerResult row and
negative_band as a standalone per-band boolean field on the
SoundPowerIntensityResult row across docs/api-reference.md and the
EN/ES site twins.
Claude-Session: https://claude.ai/code/session_013kkVt3nxi9svp1an28uHxf
feat: field survey method (ISO 10052:2021) (#128)
* feat: field survey method (ISO 10052:2021)
Add the survey (simplified) method of ISO 10052:2021 for airborne,
impact, façade and service-equipment sound insulation, plus a Table 4
reverberation-index estimator for when T is not measured.
- reverberation_index (k = 10·lg(T/T0)) and estimate_reverberation_index
(Table 4 lookup by receiving-room volume and furnishing type)
- survey_airborne_insulation: D, DnT, Dn, R' with the V/7.5 effective
area floor (Clause 3.6)
- survey_impact_insulation, survey_facade_insulation
- survey_service_equipment_level: 3-position energy average (Clause 3.16)
- SurveyAirborne/Impact/Facade/ServiceEquipment result dataclasses with
ISO 717 ratings and .plot() where a single-number rating applies
- Conformance checks (R' area rule, service equipment, Table 4 estimate)
- generate_survey_insulation figure (EN/ES × light/dark)
- Building-acoustics guide §6 and API reference rows (EN + ES)
- 22 tests covering all formulas, the estimator and validation
* review: address bot findings on the ISO 10052 survey PR
- estimate_reverberation_index: normalize the room label (strip + lower)
so " Kitchen "/"KITCHEN" resolve, and name the actual volume range in
the "not tabulated" error instead of an internal index
- survey_service_equipment_level: validate measurement dimensionality so
a scalar input raises a clean ValueError, not IndexError
- fix the four survey-function docstring citations to ISO 10052:2021
- fix the Table 4 volume-range comments to 60 <= V <= 150 (inclusive)
- conformance report: got.tolist() for plain floats in the k estimate row
- docs (EN + ES): document that reverberation_index accepts a scalar k
for service equipment; localize "Table 4" -> "Tabla 4" and "m3" -> "m³"
- add tests for room normalization, the range-named error and the
scalar-measurements guard
feat: field survey method (ISO 10052:2021) (#128)
* feat: field survey method (ISO 10052:2021)
Add the survey (simplified) method of ISO 10052:2021 for airborne,
impact, façade and service-equipment sound insulation, plus a Table 4
reverberation-index estimator for when T is not measured.
- reverberation_index (k = 10·lg(T/T0)) and estimate_reverberation_index
(Table 4 lookup by receiving-room volume and furnishing type)
- survey_airborne_insulation: D, DnT, Dn, R' with the V/7.5 effective
area floor (Clause 3.6)
- survey_impact_insulation, survey_facade_insulation
- survey_service_equipment_level: 3-position energy average (Clause 3.16)
- SurveyAirborne/Impact/Facade/ServiceEquipment result dataclasses with
ISO 717 ratings and .plot() where a single-number rating applies
- Conformance checks (R' area rule, service equipment, Table 4 estimate)
- generate_survey_insulation figure (EN/ES × light/dark)
- Building-acoustics guide §6 and API reference rows (EN + ES)
- 22 tests covering all formulas, the estimator and validation
* review: address bot findings on the ISO 10052 survey PR
- estimate_reverberation_index: normalize the room label (strip + lower)
so " Kitchen "/"KITCHEN" resolve, and name the actual volume range in
the "not tabulated" error instead of an internal index
- survey_service_equipment_level: validate measurement dimensionality so
a scalar input raises a clean ValueError, not IndexError
- fix the four survey-function docstring citations to ISO 10052:2021
- fix the Table 4 volume-range comments to 60 <= V <= 150 (inclusive)
- conformance report: got.tolist() for plain floats in the k estimate row
- docs (EN + ES): document that reverberation_index accepts a scalar k
for service equipment; localize "Table 4" -> "Tabla 4" and "m3" -> "m³"
- add tests for room normalization, the range-named error and the
scalar-measurements guard
feat: field survey method (ISO 10052:2021) (#128)
* feat: field survey method (ISO 10052:2021)
Add the survey (simplified) method of ISO 10052:2021 for airborne,
impact, façade and service-equipment sound insulation, plus a Table 4
reverberation-index estimator for when T is not measured.
- reverberation_index (k = 10·lg(T/T0)) and estimate_reverberation_index
(Table 4 lookup by receiving-room volume and furnishing type)
- survey_airborne_insulation: D, DnT, Dn, R' with the V/7.5 effective
area floor (Clause 3.6)
- survey_impact_insulation, survey_facade_insulation
- survey_service_equipment_level: 3-position energy average (Clause 3.16)
- SurveyAirborne/Impact/Facade/ServiceEquipment result dataclasses with
ISO 717 ratings and .plot() where a single-number rating applies
- Conformance checks (R' area rule, service equipment, Table 4 estimate)
- generate_survey_insulation figure (EN/ES × light/dark)
- Building-acoustics guide §6 and API reference rows (EN + ES)
- 22 tests covering all formulas, the estimator and validation
* review: address bot findings on the ISO 10052 survey PR
- estimate_reverberation_index: normalize the room label (strip + lower)
so " Kitchen "/"KITCHEN" resolve, and name the actual volume range in
the "not tabulated" error instead of an internal index
- survey_service_equipment_level: validate measurement dimensionality so
a scalar input raises a clean ValueError, not IndexError
- fix the four survey-function docstring citations to ISO 10052:2021
- fix the Table 4 volume-range comments to 60 <= V <= 150 (inclusive)
- conformance report: got.tolist() for plain floats in the k estimate row
- docs (EN + ES): document that reverberation_index accepts a scalar k
for service equipment; localize "Table 4" -> "Tabla 4" and "m3" -> "m³"
- add tests for room normalization, the range-named error and the
scalar-measurements guard
feat: field survey method (ISO 10052:2021) (#128)
* feat: field survey method (ISO 10052:2021)
Add the survey (simplified) method of ISO 10052:2021 for airborne,
impact, façade and service-equipment sound insulation, plus a Table 4
reverberation-index estimator for when T is not measured.
- reverberation_index (k = 10·lg(T/T0)) and estimate_reverberation_index
(Table 4 lookup by receiving-room volume and furnishing type)
- survey_airborne_insulation: D, DnT, Dn, R' with the V/7.5 effective
area floor (Clause 3.6)
- survey_impact_insulation, survey_facade_insulation
- survey_service_equipment_level: 3-position energy average (Clause 3.16)
- SurveyAirborne/Impact/Facade/ServiceEquipment result dataclasses with
ISO 717 ratings and .plot() where a single-number rating applies
- Conformance checks (R' area rule, service equipment, Table 4 estimate)
- generate_survey_insulation figure (EN/ES × light/dark)
- Building-acoustics guide §6 and API reference rows (EN + ES)
- 22 tests covering all formulas, the estimator and validation
* review: address bot findings on the ISO 10052 survey PR
- estimate_reverberation_index: normalize the room label (strip + lower)
so " Kitchen "/"KITCHEN" resolve, and name the actual volume range in
the "not tabulated" error instead of an internal index
- survey_service_equipment_level: validate measurement dimensionality so
a scalar input raises a clean ValueError, not IndexError
- fix the four survey-function docstring citations to ISO 10052:2021
- fix the Table 4 volume-range comments to 60 <= V <= 150 (inclusive)
- conformance report: got.tolist() for plain floats in the k estimate row
- docs (EN + ES): document that reverberation_index accepts a scalar k
for service equipment; localize "Table 4" -> "Tabla 4" and "m3" -> "m³"
- add tests for room normalization, the range-named error and the
scalar-measurements guard