Skip to content

Objective audibility of tones in noise (ISO/PAS 20065)

Standards: ISO/PAS 20065ISO 1996DIN 45681

A steady tone embedded in broadband noise stands out when it rises audibly above the noise that would otherwise mask it, the objective precondition for the tonal penalties applied in noise assessment. ISO/PAS 20065:2016 is the engineering method that quantifies this audibility: from a narrow-band FFT spectrum it derives, for every prominent tone, the audibility : how many decibels the tone level exceeds the masking threshold of the surrounding noise. It is the detailed method that ISO 1996-2:2017 defers to (the simpler Annex C route lives in environmental measurement); the mean audibility it produces feeds the ISO 1996-2 tonal adjustment .

Per-tone audibility ΔL of the nine tones of the ISO/PAS 20065 Annex E combustion-engine spectrum, with the decisive tone at 137.3 Hz highlighted and the ΔL = 0 dB threshold markedPer-tone audibility ΔL of the nine tones of the ISO/PAS 20065 Annex E combustion-engine spectrum, with the decisive tone at 137.3 Hz highlighted and the ΔL = 0 dB threshold marked

The nine tones of the ISO/PAS 20065 Annex E combustion-engine spectrum, each evaluated in its own critical band. A bar above the dashed dB line is audible over the masking noise around it, and the tallest of them — the 137.3 Hz tone at 5.0 dB — is the largest per-tone audibility of this spectrum. It is not yet the spectrum’s decisive audibility: §3 shows why the standard’s own answer is 9.18 dB.

Show the code for this figure
import matplotlib.pyplot as plt
from phonometry import psychoacoustics
# ISO/PAS 20065 Annex E combustion-engine spectrum 1: nine tones (fT, LT, LS)
# from a narrow-band spectrum with line spacing 2.7 Hz
fT = [118.4, 137.3, 158.8, 314.9, 433.4, 592.2, 629.8, 643.3, 1582.7]
LT = [64.56, 67.96, 68.63, 68.50, 73.17, 78.31, 75.00, 79.75, 71.07]
LS = [48.91, 49.22, 50.50, 52.85, 58.29, 59.53, 59.71, 61.98, 54.16]
res = psychoacoustics.assess_tones(fT, LT, LS, 2.7)
print(round(res.decisive_audibility, 2), res.decisive_frequency) # 5.01 137.3
res.plot() # per-tone audibility bars, decisive tone highlighted
plt.show()

Every later section consumes a narrow-band spectrum, and ISO/PAS 20065 is specific about which one. A reader can follow this page end to end and produce an audibility the standard would reject, because the analyser was set up differently: the arithmetic gives no sign of it.

Analyser settings (clause 4.2). A class 1 chain per IEC 61672-1 with a lower limiting frequency at or below 20 Hz, an anti-aliasing filter ahead of the digitisation, and an amplitude resolution of at least 0.1 dB. The constant line spacing shall lie between 1.9 Hz and 4.0 Hz inclusive — the 2.7 Hz of the Annex E example sits in the middle of that window, which is what assess_tones(..., 2.7) carries as its last argument. The Hanning window is mandatory, and it is where the −1.76 dB bandwidth correction of §2 comes from: another window has another effective bandwidth, so that constant, and with it every level in the chain, would be wrong.

A-weighting, before anything else (clause 5.3.2). The method is defined on an A-weighted narrow-band spectrum; the library is weighting-agnostic and applies nothing, so the caller weights the lines first. It matters because the audibility is a difference of two levels taken over one critical band: a weighting flat across the band would cancel out, but the A-curve is steepest exactly where tonal complaints live. At the 137.3 Hz tone of the example it is about −15 dB, and it climbs nearly 9 dB across that tone’s own critical band (−19.8 dB at 95.7 Hz to −11.0 dB at 197.0 Hz), so both and move, and by different amounts. The Annex E numbers on this page are already A-weighted, which is the tell-tale: anyone reproducing them from an unweighted analyser will find low-frequency tones reading high.

Averaging (clauses 4.3 and 5.1). The analyser’s own basic spectra are shorter than a second at this line spacing, so they are merged line by line (Formula 1) into spectra of approximately 3 s. That 3 s is a floor, not a preference: clause 5.1 states that shorter averaging yields unjustified audibilities, too high and too low. At least 12 time-staggered 3 s spectra are then taken, because that is what generally keeps the extended uncertainty inside ±1.5 dB, and every alternating operating state of the source must appear among them.

The two-level time structure of an ISO/PAS 20065 assessment: a 36 second record split into idle, full load and idle operating states; the analyser's sub-second basic spectra merged line by line into twelve merged spectra of 3 seconds each; each merged spectrum giving one decisive audibility, and the twelve energy-averaged by Formula 20 into the mean audibility that becomes the tonal adjustment Kt; a footer lists the class 1 chain, the 1.9 to 4.0 hertz line spacing, the mandatory Hanning window, the 0.1 decibel amplitude resolution, the A-weighting and the uncertainty ruleThe two-level time structure of an ISO/PAS 20065 assessment: a 36 second record split into idle, full load and idle operating states; the analyser's sub-second basic spectra merged line by line into twelve merged spectra of 3 seconds each; each merged spectrum giving one decisive audibility, and the twelve energy-averaged by Formula 20 into the mean audibility that becomes the tonal adjustment Kt; a footer lists the class 1 chain, the 1.9 to 4.0 hertz line spacing, the mandatory Hanning window, the 0.1 decibel amplitude resolution, the A-weighting and the uncertainty rule

The time structure behind a defensible tonal penalty. The library starts at the third band: it takes merged spectra and returns audibilities, so the first two bands are the caller’s responsibility.

When the method does not apply. A source whose level or tone frequency moves too fast to be represented by a 3 s average cannot be assessed this way at all — start-up transients, strongly speed-varying machinery. Clause 5.1 puts that exclusion in the standard rather than leaving it to judgement.

What the report has to carry (clause 7): date and place; a description of the measurement environment with the source and measurement positions and a sketch of the surroundings; air temperature, air pressure and relative humidity; mean wind speed and direction; the make, model and serial number of every instrument; the line spacing and the frequency range investigated; for every spectrum with a decisive audibility above zero, the tone frequencies and their audibilities; the mean audibility; the extended uncertainty whenever fewer than 12 spectra were averaged; and a plot of the narrow-band levels of the 3 s spectrum with the greatest . ToneAudibilityResult.report() prints the acoustic half of that list and embeds that plot; the environment and instrument halves arrive through ReportMetadata.

Each tone of frequency is evaluated inside a critical band whose width is (Formula 2)

With a geometric placement of the corner frequencies about the tone (Formulae 3–5), and , so and .

from phonometry import psychoacoustics
print(round(psychoacoustics.critical_bandwidth_engineering(137.3), 2)) # 101.36 Hz
f1, f2 = psychoacoustics.critical_band_corners(137.3)
print(round(f1, 2), round(f2, 2)) # 95.67 197.04

The mean narrow-band level of the masking noise (Formula 6, an iterative energy average of the lines in the critical band) and the tone level (Formula 8, the energy sum of the tonal lines) are derived from the narrow-band spectrum; mean_narrowband_level and tone_level do this directly (see §4). The critical-band level of the masking noise spreads over the critical bandwidth (Formula 12), the masking index accounts for the ear (Formula 13) and the audibility is their difference (Formula 14):

A supplied tone is audible when . is the line spacing (frequency resolution); the energy sums over lines carry a window correction of (−1.76 dB for the recommended Hanning window, , Formula (8)), while a single-line tone () takes its level unchanged (Formula (7), no bandwidth correction).

from phonometry import psychoacoustics
# ISO/PAS 20065 Annex E, tone at 137.3 Hz (Δf = 2.7 Hz):
# LS = 49.22 dB (Formula 6), LT = 67.96 dB (Formula 8).
print(round(psychoacoustics.tone_audibility(67.96, 49.22, 137.3, 2.7), 2)) # 5.01 dB
print(round(psychoacoustics.masking_index(137.3), 2)) # -2.02 dB

The whole method is one chain from the spectrum to the penalty, and every intermediate quantity above is a stop on it. The diagram walks the Annex E tone through that chain, down to the the mean audibility earns.

Flow diagram of the ISO/PAS 20065 engineering method on the Annex E combustion-engine spectrum: a narrow-band FFT spectrum with 2.7 hertz line spacing yields a tone at 137.3 hertz, its critical band of 101.36 hertz spans 95.67 to 197.04 hertz, the masking noise level of 49.22 decibels and tone level of 67.96 decibels give a masking threshold of 64.97 decibels with a masking index of minus 2.02 decibels, and the audibility is 5.01 decibels, the decisive value of the spectrum; a closing note maps the 6.98 decibel energy-mean audibility of the five spectra to a tonal adjustment Kt of 4 decibels through ISO 1996-2 Table J.1Flow diagram of the ISO/PAS 20065 engineering method on the Annex E combustion-engine spectrum: a narrow-band FFT spectrum with 2.7 hertz line spacing yields a tone at 137.3 hertz, its critical band of 101.36 hertz spans 95.67 to 197.04 hertz, the masking noise level of 49.22 decibels and tone level of 67.96 decibels give a masking threshold of 64.97 decibels with a masking index of minus 2.02 decibels, and the audibility is 5.01 decibels, the decisive value of the spectrum; a closing note maps the 6.98 decibel energy-mean audibility of the five spectra to a tonal adjustment Kt of 4 decibels through ISO 1996-2 Table J.1

The decisive audibility of one narrow-band spectrum is the largest tone audibility in it (clause 5.3.8). Over staggered spectra the mean audibility is their energy mean (Formula 20); a spectrum in which no tone is found contributes (Formula 21). assess_tones is the per-tone entry point: it applies Formulae (2)-(5) and (12)-(14) to each tone it is given and reports the largest, which is the decisive audibility only when no two audible tones share a critical band.

How the decisive band is selected. The method does not scan a fixed set of bands: each detected tone defines its own critical band (§1), the audibility is evaluated tone by tone, and, after Step 3 has merged audible same-band tones into FG groups rated at their most audible member (§5), the decisive audibility is simply the largest left standing (Step 4). The “decisive band” is therefore the critical band centred on whichever tone or group wins, and it is free to move from spectrum to spectrum as the source runs through its operating states; the energy mean of Formula 20 then lets the loudest (most audible) spectra dominate the reported value, which is deliberate: a tone that is clearly audible part of the time is not excused by intervals in which it disappears.

from phonometry import psychoacoustics
# Annex E combustion-engine spectrum 1: nine tones (fT, LT, LS), Δf = 2.7 Hz.
fT = [118.4, 137.3, 158.8, 314.9, 433.4, 592.2, 629.8, 643.3, 1582.7]
LT = [64.56, 67.96, 68.63, 68.50, 73.17, 78.31, 75.00, 79.75, 71.07]
LS = [48.91, 49.22, 50.50, 52.85, 58.29, 59.53, 59.71, 61.98, 54.16]
res = psychoacoustics.assess_tones(fT, LT, LS, 2.7)
print(round(res.decisive_audibility, 2), res.decisive_frequency) # 5.01 137.3
# The five spectra of the Annex E campaign, rated with Step 3 applied
# (Table E.3 decisive values), energy-averaged by Formula 20:
print(round(psychoacoustics.mean_audibility([9.18, 6.04, 7.46, 2.67, 7.17]), 2)) # 6.98 dB
res.plot(view="levels") # tone levels above their critical-band masking noise

The two numbers in that block are not the same spectrum rated twice by the same rule. The tones at 118.4, 137.3 and 158.8 Hz all fall in one critical band, so clause 5.3.8 Step 3 merges them into an FG group at their combined level dB, and the standard’s decisive value for spectrum 1 is the 9.18 dB that opens the mean_audibility list — not the 5.01 dB the per-tone call prints, which is the largest of the nine individual audibilities [0.75, 0.89, 1.02, 1.79, 1.93, 3.47, 4.39, 4.57, 5.01]. Those 4.2 dB survive the averaging: the per-tone value in place of 9.18 pulls the campaign mean from 6.98 dB to 5.98 dB, which is dB instead of 4 dB in ISO 1996-2 Table J.1. So use analyze_spectrum (§5), which runs the grouping, whenever a decisive audibility is going to be reported, and assess_tones only when the grouping has already been resolved.

The same assessment reads two ways. The audibility bars at the top of this page answer “how far above the masking threshold is each tone”; the levels view answers “what did the analyser see”, which is the view an assessment report has to defend:

Tone levels and critical-band masking noise of the ISO/PAS 20065 Annex E combustion-engine spectrum on a logarithmic frequency axis from about 96 Hz to 1.8 kHz: each tone is a stem from its critical-band masking level up to its tone level, and the decisive 137.3 Hz tone is highlighted with its critical band shadedTone levels and critical-band masking noise of the ISO/PAS 20065 Annex E combustion-engine spectrum on a logarithmic frequency axis from about 96 Hz to 1.8 kHz: each tone is a stem from its critical-band masking level up to its tone level, and the decisive 137.3 Hz tone is highlighted with its critical band shaded
Show the code for this figure
import matplotlib.pyplot as plt
from phonometry import psychoacoustics
# The Annex E combustion-engine spectrum of the snippet above.
fT = [118.4, 137.3, 158.8, 314.9, 433.4, 592.2, 629.8, 643.3, 1582.7]
LT = [64.56, 67.96, 68.63, 68.50, 73.17, 78.31, 75.00, 79.75, 71.07]
LS = [48.91, 49.22, 50.50, 52.85, 58.29, 59.53, 59.71, 61.98, 54.16]
res = psychoacoustics.assess_tones(fT, LT, LS, 2.7)
# One line: the levels view, the same one the .report() fiche embeds.
res.plot(view="levels")
plt.show()
# The default view is the per-tone audibility instead:
res.plot() # or res.plot(view="audibility")
plt.show()

Reading it left to right: each horizontal segment is the critical-band masking-noise level drawn across the band it applies to, each marker is the tone level , and the gap between them, less the masking index, is the audibility. A tone whose marker sits below its segment is masked, and no amount of level justifies a penalty for it.

3.1 Extended uncertainty of the audibility

Section titled “3.1 Extended uncertainty of the audibility”

Clause 5.4 attaches a 90 % bilateral extended uncertainty to every audibility, and clause 6 makes it mandatory whenever fewer than 12 spectra have been averaged. assess_tones computes it per tone (res.extended_uncertainties), audibility_uncertainty evaluates it straight from the spectrum lines, and mean_audibility_uncertainty propagates it to the energy-averaged audibility of a spectrum set (Annex E: for the 137.3 Hz tone against the printed 2,79).

How to read . A 90 % bilateral interval leaves 5 % in each tail, so is a one-sided 95 % statement: when the whole interval sits above 0 dB the tone is audible with at least 95 % confidence, and when the interval straddles zero the verdict is not statistically secured; the remedy is more spectra, since shrinks with the number averaged (which is exactly why clause 6 makes reporting it mandatory below 12 spectra). The same logic guards the downstream penalty: ISO 1996-2:2017 Annex J converts the mean audibility into the tonal adjustment in 1 dB steps (Table J.1: for , up to for , or the coarser 0/3/6 dB ladder of its note), so an uncertainty that spans a table boundary propagates straight into a 1–3 dB question mark on the rating level. Quoting alongside shows whether the adjustment is robust or hinges on one borderline spectrum.

The Annex E campaign is exactly that case. Its five 3 s spectra (Table E.4) carry decisive audibilities of 9.18, 6.04, 7.46, 2.67 and 7.17 dB with individual uncertainties of 3.21, 2.95, 2.44, 2.52 and 2.14 dB; the energy mean is 6.98 dB and mean_audibility_uncertainty propagates those into dB.

The five ISO/PAS 20065 Annex E measured spectra plotted as decisive audibility against run index, each with its extended uncertainty as an error bar, over horizontal bands marking the ISO 1996-2 Table J.1 tonal adjustment steps; the energy-mean audibility of 6.98 decibels is drawn as a line with a shaded band of plus or minus 1.38 decibels that crosses the boundary between Kt equal to 3 and Kt equal to 4 decibelsThe five ISO/PAS 20065 Annex E measured spectra plotted as decisive audibility against run index, each with its extended uncertainty as an error bar, over horizontal bands marking the ISO 1996-2 Table J.1 tonal adjustment steps; the energy-mean audibility of 6.98 decibels is drawn as a line with a shaded band of plus or minus 1.38 decibels that crosses the boundary between Kt equal to 3 and Kt equal to 4 decibels

Five spectra, one penalty. The mean audibility earns dB, but its uncertainty band reaches below the 6 dB boundary of ISO 1996-2 Table J.1, so dB is not excluded — and the remedy is more spectra, not a rounder number.

Show the code for this figure
# `psychoacoustics` is imported by the snippets above.
# ISO/PAS 20065 Annex E Table E.4: one decisive audibility and one extended
# uncertainty per measured 3 s spectrum.
decisive = [9.18, 6.04, 7.46, 2.67, 7.17]
uncertainty = [3.21, 2.95, 2.44, 2.52, 2.14]
mean = psychoacoustics.mean_audibility(decisive)
u = psychoacoustics.mean_audibility_uncertainty(decisive, uncertainty)
print(round(mean, 2), round(u, 2)) # 6.98 1.38 — Kt = 4 dB, Kt(ΔL − U) = 3 dB

Given the FFT lines of the critical band about a tone, mean_narrowband_level runs the iterative Formula 6 procedure (energy average, dropping any line more than 6 dB above the running , until stable within ±0.005 dB or fewer than five lines remain each side, Annex D) and tone_level sums the tonal lines contiguous with the peak (above both and ). The mean always carries the −1.76 dB Hanning bandwidth correction; the tone level carries it only when the run spans more than one line (Formulae (7)/(8)).

from phonometry import psychoacoustics
# Annex E Table E.1: the 38 lines of the 137.3 Hz critical band (Δf = 2.7 Hz).
freqs = [96.9, 99.6, 102.3, 105.0, 107.7, 110.4, 113.0, 115.7, 118.4, 121.1,
123.8, 126.5, 129.2, 131.9, 134.6, 137.3, 140.0, 142.7, 145.3, 148.0,
150.7, 153.4, 156.1, 158.8, 161.5, 164.2, 166.9, 169.6, 172.3, 175.0,
177.6, 180.3, 183.0, 185.7, 188.4, 191.1, 193.8, 196.5]
levels = [49.40, 50.68, 50.09, 53.37, 44.47, 50.91, 51.41, 59.40, 64.54, 57.57,
51.02, 50.76, 59.93, 62.94, 58.49, 65.87, 62.66, 50.25, 51.32, 52.30,
52.58, 53.15, 67.04, 67.27, 57.40, 57.17, 52.56, 51.39, 52.49, 47.68,
51.26, 49.03, 61.42, 59.52, 48.43, 50.84, 48.20, 55.95]
ls = psychoacoustics.mean_narrowband_level(levels, freqs, 137.3)
lt = psychoacoustics.tone_level(levels, freqs, 137.3, ls)
print(round(ls, 2), round(lt, 2)) # 49.22 67.96
print(round(psychoacoustics.tone_audibility(lt, ls, 137.3, 2.7), 2)) # 5.01 dB

analyze_spectrum runs the full front-end over a spectrum (mean narrow-band level per line, peak detection (Clause 5.3.8 Step 1, a tone cannot sit on a slope), tone level, the distinctness test (Clause 5.3.4: bandwidth Hz and edge steepness ), and audibility) and returns the distinct, audible tones. It then applies Step 3: audible tones sharing a critical band have their tone levels energy-summed (Formula 17, shared lines counted once, via combined_tone_level) into a combined “FG” entry rated at the most audible member, unless the exactly-two-tones-below-1000-Hz exception of §5.1 keeps them separate. The result’s group_sizes tells individual tones (1) from FG entries (), and the decisive audibility (Step 4) is the maximum over all entries.

from phonometry import psychoacoustics
# Annex E Table E.1: the 38 lines of the 137.3 Hz critical band (Δf = 2.7 Hz).
freqs = [96.9, 99.6, 102.3, 105.0, 107.7, 110.4, 113.0, 115.7, 118.4, 121.1,
123.8, 126.5, 129.2, 131.9, 134.6, 137.3, 140.0, 142.7, 145.3, 148.0,
150.7, 153.4, 156.1, 158.8, 161.5, 164.2, 166.9, 169.6, 172.3, 175.0,
177.6, 180.3, 183.0, 185.7, 188.4, 191.1, 193.8, 196.5]
levels = [49.40, 50.68, 50.09, 53.37, 44.47, 50.91, 51.41, 59.40, 64.54, 57.57,
51.02, 50.76, 59.93, 62.94, 58.49, 65.87, 62.66, 50.25, 51.32, 52.30,
52.58, 53.15, 67.04, 67.27, 57.40, 57.17, 52.56, 51.39, 52.49, 47.68,
51.26, 49.03, 61.42, 59.52, 48.43, 50.84, 48.20, 55.95]
# Same Table E.1 spectrum as above.
res = psychoacoustics.analyze_spectrum(levels, freqs, 2.7)
singles = res.group_sizes == 1
print([round(f, 1) for f in res.tone_frequencies[singles]]) # [118.4, 137.3, 158.8]
# Step 3 already combined the three same-band tones into an FG entry:
fg = res.group_sizes > 1
print(int(res.group_sizes[fg][0]), round(float(res.tone_levels[fg][0]), 2)) # 3 72.15
# The same Formula 17 combination, called directly (LS from Table E.2):
lt_fg = psychoacoustics.combined_tone_level(levels, freqs, [118.4, 137.3, 158.8],
[48.91, 49.22, 50.50])
print(round(lt_fg, 2)) # 72.15
res.plot() # the detected entries, FG groups included, as audibility bars

Reproducing a decisive audibility exactly needs the complete narrow-band spectrum: Table E.1 is truncated to the 137.3 Hz critical band, so the 158.8 Hz tone’s mean narrow-band level is under-estimated from it (the algorithm itself matches the parent standard DIN 45681:2005-03 reference program). The peak detection and FG combination are verified against the Annex E worked example (the three tone frequencies and ).

When exactly two tones share a critical band and both lie below 1000 Hz, the ear can still tell them apart (so they are rated separately rather than FG-combined) if their frequency difference (Formula 18) exceeds

evaluated at the more prominent tone (the larger audibility ). The threshold bottoms out at 21 Hz at and grows on either side. two_tone_separation_frequency gives ; resolve_tones_separately applies the decision.

The ISO/PAS 20065 Formula 19 separation threshold fD plotted against the frequency of the more audible tone on a logarithmic axis from 88 hertz to 1 kilohertz: a U-shaped curve with its minimum of 21 hertz at 212 hertz, rising to 34 hertz at 88 hertz and 82 hertz at 1 kilohertz; the region above the curve is shaded and labelled rated separately, the region below labelled energy-summed into one FG entry, and the Annex E pair at 137.3 hertz with a separation of 18.9 hertz is marked below the curveThe ISO/PAS 20065 Formula 19 separation threshold fD plotted against the frequency of the more audible tone on a logarithmic axis from 88 hertz to 1 kilohertz: a U-shaped curve with its minimum of 21 hertz at 212 hertz, rising to 34 hertz at 88 hertz and 82 hertz at 1 kilohertz; the region above the curve is shaded and labelled rated separately, the region below labelled energy-summed into one FG entry, and the Annex E pair at 137.3 hertz with a separation of 18.9 hertz is marked below the curve

Where the ear stops resolving two tones in one critical band. The threshold is narrowest around 212 Hz and widens steeply above 500 Hz — at 1 kHz two tones must be 82 Hz apart to be rated separately, which is most of the critical band. The Annex E pair sits just below the curve and is therefore combined.

Show the code for this figure
import matplotlib.pyplot as plt
import numpy as np
# `psychoacoustics` is imported by the snippets above.
ft_grid = np.logspace(np.log10(88.0), np.log10(1000.0), 400)
fd = [psychoacoustics.two_tone_separation_frequency(f) for f in ft_grid]
plt.semilogx(ft_grid, fd, label="Threshold fD (Formula 19)")
plt.plot([212.0], [21.0], "o") # the 21 Hz minimum
plt.plot([137.3], [18.9], "s") # the Annex E pair, 118.4 and 137.3 Hz
plt.xlabel("Frequency of the more audible tone fT [Hz]")
plt.ylabel("Frequency separation |fT1 - fT2| [Hz]")
plt.legend()
plt.show()
from phonometry import psychoacoustics
psychoacoustics.two_tone_separation_frequency(212.0) # 21.0 Hz (minimum)
psychoacoustics.resolve_tones_separately(200.0, 260.0, 3.0, 2.0) # True → rate separately
psychoacoustics.resolve_tones_separately(118.4, 137.3, 4.0, 5.0) # False → combine (Δf < fD)

The fiche uses the ISO 1996-2 reporting symbols: the decisive audibility is written and the tonal adjustment , which are the and of the sections above.

ToneAudibilityResult.report(path) renders a one-page PDF fiche laid out like a tonal-assessment report of an environmental-noise laboratory, following the ISO 1996-2:2017 Annex J engineering method: a standard-basis line, an optional metadata header block (source/situation, client, measurement position, instrumentation and date, with the analysis line spacing read from the result), a full-width table of the key quantities for every detected tone (tone frequency , entry type, tone level , critical-band masking-noise level , critical bandwidth and the audibility ) above the level-versus-frequency analysis plot with the tones and their critical-band masking noise marked, the boxed decisive audibility together with the derived tonal adjustment (Table J.1), an optional PASS/FAIL verdict row and a prominence note, and a footer with the fixed disclaimer.

It uses the same ReportMetadata container and rendering engine as the ISO 532-1 loudness fiche; a supplied requirement is read as the maximum acceptable decisive audibility in dB (a quieter tone passes). Rendering needs reportlab and, for the figure the fiche embeds, matplotlib (pip install "phonometry[report,plot]"); only engine="reportlab" is supported. The fiche renders in English by default; pass language="es" for a Spanish fiche (translated fixed strings and a comma decimal separator), e.g. res.report("tone_fiche_es.pdf", language="es").

from phonometry import psychoacoustics, ReportMetadata
# The Annex E combustion-engine spectrum from §4/§5 (analyze_spectrum).
res = psychoacoustics.analyze_spectrum(levels, freqs, 2.7)
res.report(
"tone_fiche.pdf",
metadata=ReportMetadata(
specimen="Combustion engine, steady operation",
measurement_standard="ISO 1996-2",
laboratory="Phonometry Reference Laboratory",
requirement=6.0, # maximum acceptable ΔL_ta (dB)
),
) # decisive ΔL_ta (dB) and K (dB, Table J.1)

The example fiche is regenerated with make reports and kept rendered in the repository; click the preview to open the PDF.

ISO 1996-2 tonal audibility example report (PDF)

One-page tonal-assessment fiche: a metadata header, a per-tone table of the tone level Lpt, the critical-band masking-noise level Lpn, the critical bandwidth and the audibility, the level-versus-frequency analysis plot with the tones and their masking noise marked, the boxed decisive ΔL_ta = 9.1 dB with the tonal adjustment K = 5 dB (ISO 1996-2:2017 Table J.1) and a FAIL verdict against a 6 dB audibility limit.

Download the report (PDF)

Tonal audibility fiche (ToneAudibilityResult.report), decisive ΔL_ta in dB with the tonal adjustment K.
  • Covered

    The ISO/PAS 20065:2016 engineering method in full: the clause 4.2 analyser requirements and the clause 4.3 merging of basic spectra that the input rests on, with the clause 5.1 acceptance conditions and the clause 7 reporting list; the critical bandwidth and corner frequencies (Formulae 2 to 5), the mean narrow-band level and tone level (Formulae 6 and 8, Annex D), the critical-band masking level , the masking index and the audibility (Formulae 12 to 14), peak detection and the distinctness test (clauses 5.3.8 and 5.3.4), the multi-tone FG combination (Formula 17) and the two-tones-below-1000-Hz exception (Formulae 18/19), the decisive and energy-mean audibility (Formula 20) and the clause 5.4/6 extended uncertainty , all through psychoacoustics.analyze_spectrum and assess_tones. ISO 1996-2:2017 Annex J is covered as far as it maps the mean audibility to the tonal adjustment (Table J.1).

  • Not covered

    The distinctness edge-steepness test follows the DIN 45681:2005-03 reading (its executable reference program), not the asymmetric formulas printed in the ISO/PAS 20065 text, which contradict it, recorded in the errata registry. Building the narrow-band FFT spectrum itself from a raw time-domain recording is not part of this module: every function here takes an already-computed spectrum (levels and frequencies), and §0 states what that spectrum has to be — including the clause 5.3.2 A-weighting, which the caller applies because the module is weighting agnostic.