Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ ci:
- changed-files:
- any-glob-to-any-file: ["src/phonometry/environmental/**", "tests/environmental/**"]

"area: filters":
- changed-files:
- any-glob-to-any-file: ["src/phonometry/filters/**", "tests/filters/**"]

"area: hearing":
- changed-files:
- any-glob-to-any-file: ["src/phonometry/hearing/**", "tests/hearing/**"]
Expand All @@ -171,6 +175,10 @@ ci:
- changed-files:
- any-glob-to-any-file: ["src/phonometry/room/**", "tests/room/**"]

"area: signals":
- changed-files:
- any-glob-to-any-file: ["src/phonometry/signals/**", "tests/signals/**"]

"area: simulation":
- changed-files:
- any-glob-to-any-file: ["src/phonometry/simulation/**", "tests/simulation/**", "scripts/fdtd2d.py"]
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,38 @@ jobs:
# for the whole set) and needs no rendering stack of its own.
run: python scripts/check_figure_contrast.py

# The Python snippets printed in the guides must run. They are the first
# thing a reader copies, and nothing executed them until this job existed:
# the metrology split shipped seven blocks where `from phonometry import
# signals` sat next to `from scipy import signal` and silently rebound the
# name, which Python does not warn about and no other gate can see. The
# script also holds the English and Spanish pages to the same API and skips,
# with a written reason, the pages whose blocks are excerpts of a workflow
# rather than a script.
doc-snippets:
name: Documentation snippets run
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Python 3.13
uses: actions/setup-python@v7
with:
python-version: "3.13"
cache: 'pip'
- name: Install dependencies
# The guides plot and print fiches, so the snippets need the figure and
# report stacks as well as the package itself.
run: |
python -m pip install --upgrade pip
pip install -e .
pip install -r requirements-figures.txt -r requirements-reports.txt
- name: Run every snippet the guides print
run: python scripts/check_doc_snippets.py

# The committed example .report() fiches (.github/reports) must match a fresh
# `make reports` run. Same drift gate as the figures, one layer further down
# the pipeline: the fiches are what the documentation links to as worked
Expand Down
58 changes: 58 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

### Changed

- `phonometry.metrology` is three packages. It had grown to 21 modules across
four unrelated subjects, and every layer above it had already worked around
that: the generated reference spread it over six sections, the sidebar over
four groups, and the name predicted neither `cepstrum` nor `signals`. The
filter banks, the frequency and time weightings, the parametric EQ and the
IEC 61260-1 / IEC 61672-1 class verification are now `phonometry.filters`;
the general signal analysis (levels, Welch and multitaper spectra, coherence,
time-frequency, correlation, envelope, cepstrum, phase, synchronous
averaging, test signals) is `phonometry.signals`; and `phonometry.metrology`
keeps what gives it its name, the calibration, the GUM uncertainty, the data
qualification and the IEC 61043 intensity-instrument class check. Four
modules are renamed with the move, each dropping a prefix its package now
carries: `filter_design` to `filters.design`,
`parametric_filters` to `filters.weighting` (it is the A/C/G and time
weightings, which is what people look for), `signals` to
`signals.test_signals` and `random_data` to
`metrology.data_qualification`, the name its documentation page already had.
Nothing moves in the flat API: `from phonometry import leq, octave_filter`
is what it always was, and that is how the documentation leads.

- Every 3.x module path still imports, and so does every name read through the
namespace it left. `import phonometry.metrology.levels` and
`from phonometry.metrology import spectra` resolve to the relocated module
and warn on attribute access, the same PEP 562 shim the 3.2 modularization
used; `metrology.leq(...)` after `from phonometry import metrology` warns and
delegates too, which the module-path shims alone would not have covered, and
the namespace form is the one the documentation leads with. The aliases are
removed in 5.0, a release later than the 3.x ones, so the rename notice now
names the release that removes it instead of assuming 4.0. Resolution goes
through the public `__all__` of the packages the names moved to, so a name
that stops being public stops resolving through the old namespace as well,
and `dir(metrology)` still lists them, since a PEP 562 hook is invisible to
it and they would otherwise vanish from tab completion a release before they
stop working. The one form the hook cannot serve is
`from phonometry.metrology import *`, which now brings the narrowed API
rather than everything the package used to re-export; the explicit forms all
keep working.

- The generated reference is keyed by subpackage. Its sections were a fourth
naming of the same material (`levels`, `spectra`, `correlation` for what the
code called `metrology`), so a reader who knew where a function lived could
not predict where its page lived. They are now `filters`, `signals` and
`metrology`, one per package, and the pages move with them
(`reference/api/spectra/cepstrum` becomes `reference/api/signals/cepstrum`).
The consistency contract in `scripts/api_taxonomy.py` is what enforces it:
five sections drew from `metrology` under four different names and now three
draw from three packages under their own. The sections that deliberately
span two parents are untouched, and one of them is why the rule is not yet
universal: `metrology.intensity_compliance` is still documented with the
intensity chain it verifies, in the `power` section.

- CI fails when `.github/reports` no longer matches a fresh `make reports`
run, which is the reason the fiches were able to drift for weeks in the
first place: the conformance report, the generated API reference, the
Expand Down Expand Up @@ -1589,6 +1640,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
programme loudness names the AES convention as it is published instead of
translating it.

### Deprecated

- The pre-4.0 `phonometry.metrology.*` module paths and the names read from
the `metrology` namespace that now live in `filters` or `signals` (see
Changed). Both warn on use and are removed in 5.0, one release after the
3.x aliases.

### Fixed

- The committed example `.report()` fiches were not checked against the code
Expand Down
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ llms:
pypi-readme:
$(PYTHON) scripts/generate_pypi_readme.py

# Run every Python snippet the guides print, hold the two languages to the
# same API and reject a block that shadows a name it imported (see the
# doc-snippets job in python-app.yml). `make snippets-static` skips the
# execution pass, which is the slow half.
snippets:
$(PYTHON) scripts/check_doc_snippets.py

snippets-static:
$(PYTHON) scripts/check_doc_snippets.py --static

# Regenerate the committed Starlight API reference (site/src/content/docs/
# reference/api + site/src/generated/api-sidebar.mjs) from the source
# docstrings. CI fails if this drifts (see the api-docs job in python-app.yml).
Expand Down Expand Up @@ -200,4 +210,5 @@ check: lint security test

.PHONY: install lint format security snyk sonar graphs figure-contrast figures reports \
animations posters brand lighthouse \
llms pypi-readme api-docs site-reports conformance install-hooks test coverage check
llms pypi-readme api-docs site-reports conformance install-hooks test coverage check \
snippets snippets-static
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,15 @@ leave `[perf]` out.

```python
import numpy as np
from phonometry import metrology
from phonometry import filters

fs = 48000
t = np.linspace(0, 1, fs, endpoint=False)
# Composite signal: 100Hz + 1000Hz
signal = np.sin(2 * np.pi * 100 * t) + np.sin(2 * np.pi * 1000 * t)

# Apply 1/3 octave filter bank
spl, freq = metrology.octave_filter(signal, fs=fs, fraction=3)
spl, freq = filters.octave_filter(signal, fs=fs, fraction=3)

print(f"Bands: {freq}")
print(f"SPL [dB]: {spl}")
Expand All @@ -99,10 +99,12 @@ tl = underwater.transmission_loss(...)

| Namespace | Coverage |
| :--- | :--- |
| `metrology` | 1/1, 1/3 and arbitrary fractional octave filter banks (stable SOS + multirate decimation) in five architectures with per-band class verdicts (IEC 61260-1 / ANSI S1.11); A/C/Z weighting within IEC 61672-1 class 1 tolerances plus G weighting (ISO 7196); Fast/Slow/Impulse ballistics, Leq, SEL, L10/L50/L90, noise dose (IEC 61252); octave spectrogram and zero-phase filtering; physical SPL calibration with IEC 60942 stability validation and dBFS modes; calibrated Welch PSD/CSD with chi-square confidence intervals, coherent output spectrum, 1/n-octave smoothing and colored-noise generators (Bendat & Piersol); MISO multiple/partial coherence; correlation and GCC time-delay estimation (Knapp & Carter); Hilbert envelope, cepstrum and echoes, time synchronous averaging, calibrated STFT and zoom FFT; Golay/shaped-sweep system measurement with regularized inversion; IEC 60268-1 tone bursts and resampling; GUM uncertainty (ISO/IEC Guide 98-3) and Bendat & Piersol data qualification |
| `filters` | 1/1, 1/3 and arbitrary fractional octave filter banks (stable SOS + multirate decimation) in five architectures with per-band class verdicts (IEC 61260-1 / ANSI S1.11); A/C/Z weighting within IEC 61672-1 class 1 tolerances plus G weighting (ISO 7196); Fast/Slow/Impulse ballistics; octave spectrogram and zero-phase filtering; RBJ parametric equalizer sections |
| `signals` | Leq, SEL, L10/L50/L90 and noise dose (IEC 61252); calibrated Welch PSD/CSD with chi-square confidence intervals, coherent output spectrum, 1/n-octave smoothing and colored-noise generators (Bendat & Piersol); MISO multiple/partial coherence; correlation and GCC time-delay estimation (Knapp & Carter); Hilbert envelope, cepstrum and echoes, time synchronous averaging, calibrated STFT and zoom FFT; regularized inverse filtering for system measurement; IEC 60268-1 tone bursts and resampling |
| `metrology` | Physical SPL calibration with IEC 60942 stability validation and dBFS modes; GUM uncertainty with Monte Carlo (ISO/IEC Guide 98-3 and Supplement 1); Bendat & Piersol data qualification (stationarity, trends, level crossings, peak statistics); IEC 61043 intensity-instrument class verification |
| `psychoacoustics` | Loudness in sones three ways: Zwicker (ISO 532-1 Annex B validated), Moore-Glasberg stationary and time-varying (ISO 532-2/3) and Sottek Hearing Model (ECMA-418-2); DIN 45692 sharpness; ECMA-418-2 tonality, roughness (asper) and fluctuation strength (vacil_HMS); tone prominence TNR/PR (ECMA-418-1); tonal audibility (ISO/PAS 20065); Fastl & Zwicker psychoacoustic annoyance; ISO 226:2023 contours |
| `hearing` | Speech Transmission Index STI/STIPA with signal generator (IEC 60268-16 Ed. 5); Speech Intelligibility Index (ANSI S3.5-1997); STOI and ESTOI; age-related thresholds (ISO 7029) and reference thresholds (ISO 389-7); noise-induced hearing loss with HTLAN (ISO 1999); daily noise exposure LEX,8h with Annex C uncertainty (ISO 9612) |
| `room` | Swept-sine/MLS impulse responses (ISO 18233); EDT/T20/T30/C50/C80/Ts (ISO 3382-1/2); open-plan speech metrics (ISO 3382-3); reverberation-room absorption (ISO 354); reverberation-time prediction (Sabine to Arau-Puchades); total absorption of furnished rooms (EN 12354-6); image-source impulse responses and the steady-state field; room-noise criteria NC and RC Mark II (ANSI/ASA S12.2) |
| `room` | Swept-sine/MLS/Golay impulse responses (ISO 18233); EDT/T20/T30/C50/C80/Ts (ISO 3382-1/2); open-plan speech metrics (ISO 3382-3); reverberation-room absorption (ISO 354); reverberation-time prediction (Sabine to Arau-Puchades); total absorption of furnished rooms (EN 12354-6); image-source impulse responses and the steady-state field; room-noise criteria NC and RC Mark II (ANSI/ASA S12.2) |
| `building` | Field airborne, impact and façade insulation with R′w/DnT,w/L′nT,w/D2m,nT,w and C/Ctr/CI (ISO 16283-1/2/3, ISO 717-1/2); laboratory R/Ln (ISO 10140) and survey method (ISO 10052); insulation by intensity (ISO 15186); flanking transmission measurement and prediction (ISO 10848, EN 12354-1/2) and façade/outdoor radiation (EN 12354-3/4); measurement uncertainty (ISO 12999-1); panel transmission theory (mass law, coincidence, double walls, slits and apertures); floor-covering improvement (ISO 16251-1); reception-plate power (EN 15657) and installed structure-borne prediction (EN 12354-5); dynamic stiffness (EN 29052-1) |
| `materials` | Absorption ratings αw with classes (ISO 11654) and uncertainty (ISO 12999-2); impedance-tube absorption, impedance and transmission loss (ISO 10534-1/2, ASTM E2611) plus a virtual FDTD tube; porous and multilayer absorber models (Delany-Bazley, Miki, JCA, TMM with MPP and membranes); slow-sound metamaterial absorbers at critical coupling; scattering and diffusion coefficients (ISO 17497-1/2); Schroeder diffuser design and far-field prediction; deep-subwavelength metadiffusers; in-situ road-surface absorption (ISO 13472-1/2); airflow resistance (ISO 9053-1/2) |
| `emission` | Sound power by enveloping surface (ISO 3744/3746), reverberation room (ISO 3741), precision anechoic rooms (ISO 3745) and intensity scanning with field indicators and grades (ISO 9614-2/3); two-microphone p-p intensity (IEC 61043, ISO 9614-1); sound power from surface vibration (ISO/TS 7849); noise-emission declarations (ISO 4871) |
Expand Down
10 changes: 6 additions & 4 deletions README_PYPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ leave `[perf]` out.

```python
import numpy as np
from phonometry import metrology
from phonometry import filters

fs = 48000
t = np.linspace(0, 1, fs, endpoint=False)
# Composite signal: 100Hz + 1000Hz
signal = np.sin(2 * np.pi * 100 * t) + np.sin(2 * np.pi * 1000 * t)

# Apply 1/3 octave filter bank
spl, freq = metrology.octave_filter(signal, fs=fs, fraction=3)
spl, freq = filters.octave_filter(signal, fs=fs, fraction=3)

print(f"Bands: {freq}")
print(f"SPL [dB]: {spl}")
Expand All @@ -106,10 +106,12 @@ tl = underwater.transmission_loss(...)

| Namespace | Coverage |
| :--- | :--- |
| `metrology` | 1/1, 1/3 and arbitrary fractional octave filter banks (stable SOS + multirate decimation) in five architectures with per-band class verdicts (IEC 61260-1 / ANSI S1.11); A/C/Z weighting within IEC 61672-1 class 1 tolerances plus G weighting (ISO 7196); Fast/Slow/Impulse ballistics, Leq, SEL, L10/L50/L90, noise dose (IEC 61252); octave spectrogram and zero-phase filtering; physical SPL calibration with IEC 60942 stability validation and dBFS modes; calibrated Welch PSD/CSD with chi-square confidence intervals, coherent output spectrum, 1/n-octave smoothing and colored-noise generators (Bendat & Piersol); MISO multiple/partial coherence; correlation and GCC time-delay estimation (Knapp & Carter); Hilbert envelope, cepstrum and echoes, time synchronous averaging, calibrated STFT and zoom FFT; Golay/shaped-sweep system measurement with regularized inversion; IEC 60268-1 tone bursts and resampling; GUM uncertainty (ISO/IEC Guide 98-3) and Bendat & Piersol data qualification |
| `filters` | 1/1, 1/3 and arbitrary fractional octave filter banks (stable SOS + multirate decimation) in five architectures with per-band class verdicts (IEC 61260-1 / ANSI S1.11); A/C/Z weighting within IEC 61672-1 class 1 tolerances plus G weighting (ISO 7196); Fast/Slow/Impulse ballistics; octave spectrogram and zero-phase filtering; RBJ parametric equalizer sections |
| `signals` | Leq, SEL, L10/L50/L90 and noise dose (IEC 61252); calibrated Welch PSD/CSD with chi-square confidence intervals, coherent output spectrum, 1/n-octave smoothing and colored-noise generators (Bendat & Piersol); MISO multiple/partial coherence; correlation and GCC time-delay estimation (Knapp & Carter); Hilbert envelope, cepstrum and echoes, time synchronous averaging, calibrated STFT and zoom FFT; regularized inverse filtering for system measurement; IEC 60268-1 tone bursts and resampling |
| `metrology` | Physical SPL calibration with IEC 60942 stability validation and dBFS modes; GUM uncertainty with Monte Carlo (ISO/IEC Guide 98-3 and Supplement 1); Bendat & Piersol data qualification (stationarity, trends, level crossings, peak statistics); IEC 61043 intensity-instrument class verification |
| `psychoacoustics` | Loudness in sones three ways: Zwicker (ISO 532-1 Annex B validated), Moore-Glasberg stationary and time-varying (ISO 532-2/3) and Sottek Hearing Model (ECMA-418-2); DIN 45692 sharpness; ECMA-418-2 tonality, roughness (asper) and fluctuation strength (vacil_HMS); tone prominence TNR/PR (ECMA-418-1); tonal audibility (ISO/PAS 20065); Fastl & Zwicker psychoacoustic annoyance; ISO 226:2023 contours |
| `hearing` | Speech Transmission Index STI/STIPA with signal generator (IEC 60268-16 Ed. 5); Speech Intelligibility Index (ANSI S3.5-1997); STOI and ESTOI; age-related thresholds (ISO 7029) and reference thresholds (ISO 389-7); noise-induced hearing loss with HTLAN (ISO 1999); daily noise exposure LEX,8h with Annex C uncertainty (ISO 9612) |
| `room` | Swept-sine/MLS impulse responses (ISO 18233); EDT/T20/T30/C50/C80/Ts (ISO 3382-1/2); open-plan speech metrics (ISO 3382-3); reverberation-room absorption (ISO 354); reverberation-time prediction (Sabine to Arau-Puchades); total absorption of furnished rooms (EN 12354-6); image-source impulse responses and the steady-state field; room-noise criteria NC and RC Mark II (ANSI/ASA S12.2) |
| `room` | Swept-sine/MLS/Golay impulse responses (ISO 18233); EDT/T20/T30/C50/C80/Ts (ISO 3382-1/2); open-plan speech metrics (ISO 3382-3); reverberation-room absorption (ISO 354); reverberation-time prediction (Sabine to Arau-Puchades); total absorption of furnished rooms (EN 12354-6); image-source impulse responses and the steady-state field; room-noise criteria NC and RC Mark II (ANSI/ASA S12.2) |
| `building` | Field airborne, impact and façade insulation with R′w/DnT,w/L′nT,w/D2m,nT,w and C/Ctr/CI (ISO 16283-1/2/3, ISO 717-1/2); laboratory R/Ln (ISO 10140) and survey method (ISO 10052); insulation by intensity (ISO 15186); flanking transmission measurement and prediction (ISO 10848, EN 12354-1/2) and façade/outdoor radiation (EN 12354-3/4); measurement uncertainty (ISO 12999-1); panel transmission theory (mass law, coincidence, double walls, slits and apertures); floor-covering improvement (ISO 16251-1); reception-plate power (EN 15657) and installed structure-borne prediction (EN 12354-5); dynamic stiffness (EN 29052-1) |
| `materials` | Absorption ratings αw with classes (ISO 11654) and uncertainty (ISO 12999-2); impedance-tube absorption, impedance and transmission loss (ISO 10534-1/2, ASTM E2611) plus a virtual FDTD tube; porous and multilayer absorber models (Delany-Bazley, Miki, JCA, TMM with MPP and membranes); slow-sound metamaterial absorbers at critical coupling; scattering and diffusion coefficients (ISO 17497-1/2); Schroeder diffuser design and far-field prediction; deep-subwavelength metadiffusers; in-situ road-surface absorption (ISO 13472-1/2); airflow resistance (ISO 9053-1/2) |
| `emission` | Sound power by enveloping surface (ISO 3744/3746), reverberation room (ISO 3741), precision anechoic rooms (ISO 3745) and intensity scanning with field indicators and grades (ISO 9614-2/3); two-microphone p-p intensity (IEC 61043, ISO 9614-1); sound power from surface vibration (ISO/TS 7849); noise-emission declarations (ISO 4871) |
Expand Down
4 changes: 2 additions & 2 deletions docs/aircraft-noise.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ filtering itself is covered by the library's IEC 61260 class-2 filter
verification (`verify_filter_class`).

```python
from phonometry import metrology
from phonometry import filters

report = metrology.verify_aircraft_noise_system(
report = filters.verify_aircraft_noise_system(
directional={4000.0: {30: 0.4, 60: 0.9, 90: 1.9, 120: 2.4, 150: 2.4}},
frequency_response={1000.0: 1.2},
)
Expand Down
Loading