Psychoacoustic annoyance and fluctuation strength
Key references: Fastl & Zwicker 2007Osses Vecchi et al. 2016
How annoying a sound is depends on more than how loud it is. Fastl & Zwicker,
Psychoacoustics: Facts and Models, combine four psychoacoustic sensations
(loudness, sharpness, roughness and fluctuation strength) into a
single psychoacoustic annoyance PA, a scalar that grows with loudness and
is lifted further when the sound is sharp, rough or slowly fluctuating. This page
covers the exact PA model (Eqs 16.2–16.4), the fluctuation strength it
consumes, both the closed form for amplitude-modulated broadband noise
(Eq. 10.2) and the Osses et al. (2016) signal model, and the signal
convenience that derives all four sensations from a recording.
Show the code for this figure
import matplotlib.pyplot as pltimport numpy as npfrom phonometry import psychoacoustics
n5 = np.linspace(4.0, 60.0, 200)profiles = [ ("Baseline: S = 1.75 acum, F = R = 0", 1.75, 0.0, 0.0), ("Sharp: S = 3.5 acum", 3.5, 0.0, 0.0), ("Rough + fluctuating: F = 1.2 vacil, R = 0.7 asper", 2.0, 1.2, 0.7),]fig, ax = plt.subplots()for label, s, f, r in profiles: pa = [psychoacoustics.psychoacoustic_annoyance(v, s, f, r).annoyance for v in n5] ax.plot(n5, pa, label=label)
ex = psychoacoustics.psychoacoustic_annoyance(30.0, 2.0, 0.5, 0.3)ax.plot([30.0], [ex.annoyance], "o", label=f"Worked example (PA = {ex.annoyance:.2f})")ax.set_xlabel("Percentile loudness N5 [sone]")ax.set_ylabel("Psychoacoustic annoyance PA")ax.legend()plt.show()1. The four sensations
Section titled “1. The four sensations”Psychoacoustic annoyance rests on four hearing sensations, each with its own model and unit in the library:
- Loudness: the percentile loudness
N5(the loudness exceeded 5 % of the time), in sone, from the ISO 532-1 Zwicker time-varying model (loudness_zwicker, see Loudness). - Sharpness
S, in acum: the spectral balance towards high frequencies, DIN 45692 (sharpness_din). - Roughness
R, in asper: the harshness of fast (~70 Hz) amplitude modulation, ECMA-418-2 Sottek model (roughness_ecma). - Fluctuation strength
F, in vacil: the sensation of slow (~4 Hz) loudness fluctuation (§3 below).
2. Psychoacoustic annoyance (Eqs 16.2–16.4)
Section titled “2. Psychoacoustic annoyance (Eqs 16.2–16.4)”The exact model (Fastl & Zwicker Eq. 16.2; origin Widmann 1992) scales N5 by a
factor that grows with the sharpness weighting wS and the combined
roughness/fluctuation weighting wFR:
wS is zero for S ≤ 1.75 acum (sharpness only adds annoyance above that
threshold); wFR weights roughness more heavily than fluctuation strength
(0.6 vs 0.4). psychoacoustic_annoyance takes the four quantities directly and
returns the annoyance together with the two intermediate weightings:
from phonometry import psychoacoustics
res = psychoacoustics.psychoacoustic_annoyance(30.0, 2.0, 0.5, 0.3) # N5, S, F, Rprint(round(res.annoyance, 4)) # 37.0478print(round(res.w_s, 4), round(res.w_fr, 4)) # 0.1001 0.2125
res.plot() # PA beside its wS and wFR weightings (needs matplotlib)The figure above sweeps PA against N5 for three profiles: a neutral baseline
(S = 1.75 acum, F = R = 0, so PA = N5), a sharp sound and a
rough-and-fluctuating sound, both lifted above the baseline, with the worked
example marked.
2.1 From a signal (engineering estimate)
Section titled “2.1 From a signal (engineering estimate)”psychoacoustic_annoyance_from_signal is a convenience that derives all four
sensations from a calibrated pressure signal and combines them: N5 from the
ISO 532-1 Zwicker time-varying loudness, S from DIN 45692 sharpness, R from
the ECMA-418-2 Sottek roughness and F from the fluctuation-strength signal
model.
from phonometry import psychoacoustics
res = psychoacoustics.psychoacoustic_annoyance_from_signal(x, fs, field="free")print(res.annoyance, res.n5, res.sharpness, res.roughness, res.fluctuation_strength)
res.plot() # the same PA / wS / wFR view, now from the four derived sensations3. Fluctuation strength
Section titled “3. Fluctuation strength”Fluctuation strength F (vacil) quantifies the perception of slow loudness
fluctuation. Like roughness it is a band-pass sensation of the modulation
frequency, but it peaks about an order of magnitude lower, at fmod ≈ 4 Hz
rather than the ~70 Hz roughness peak. By definition, a 1 kHz tone at 60 dB,
100 % amplitude-modulated at 4 Hz, produces 1 vacil. This page covers the
Fastl & Zwicker models; the normative Sottek-model fluctuation strength of
ECMA-418-2 Clause 9 lives in
Sound Quality Metrics.
Show the code for this figure
import matplotlib.pyplot as pltimport numpy as npfrom phonometry import psychoacoustics
# Exact closed form (Eq. 10.2), AM broadband noise at 60 dB, 100 % modulation:fmod = np.logspace(np.log10(0.5), np.log10(32.0), 240)f_bbn = [psychoacoustics.fluctuation_strength_am_noise(60.0, 1.0, fm) for fm in fmod]
# Osses 2016 signal model on a 1 kHz / 70 dB AM tone over the same sweep:fs = 48000t = np.arange(int(2.0 * fs)) / fscarrier = np.sin(2 * np.pi * 1000 * t)fm_tone = [1.0, 2.0, 4.0, 8.0, 16.0, 32.0]f_tone = []for fm in fm_tone: am = (1.0 + np.sin(2 * np.pi * fm * t)) * carrier am = am / np.sqrt(np.mean(am ** 2)) * 2e-5 * 10 ** (70 / 20) f_tone.append(psychoacoustics.fluctuation_strength(am, float(fs)).fluctuation_strength)
fig, ax = plt.subplots()ax.semilogx(fmod, f_bbn, label="AM broadband noise (closed form)")ax2 = ax.twinx()ax2.plot(fm_tone, f_tone, "s--", color="tab:green", label="AM tone (signal model)")ax.axvline(4.0, ls="--", color="0.4")ax.set_xlabel("Modulation frequency f_mod [Hz]")ax.set_ylabel("Fluctuation strength F [vacil]")h1, l1 = ax.get_legend_handles_labels()h2, l2 = ax2.get_legend_handles_labels()ax.legend(h1 + h2, l1 + l2, loc="upper right")plt.show()3.1 Closed form for AM broadband noise (Eq. 10.2)
Section titled “3.1 Closed form for AM broadband noise (Eq. 10.2)”For sinusoidally amplitude-modulated broadband noise, Fastl & Zwicker give a
closed form (Eq. 10.2) in modulation factor m, level L and modulation
frequency fmod:
The denominator is the 4 Hz band-pass: it bottoms out near fmod ≈ 3.7 Hz and
rises on either side. The result is clamped at 0 (the sensation vanishes below
~20 dB or m < 0.2). This exact form is the value to quote for AM broadband
noise.
from phonometry import psychoacoustics
print(round(psychoacoustics.fluctuation_strength_am_noise(60.0, 1.0, 4.0), 4)) # 3.6943 vacil3.2 The Osses 2016 signal model
Section titled “3.2 The Osses 2016 signal model”fluctuation_strength implements the Osses et al. (2016) signal model: it builds
an excitation pattern over 47 auditory filters, extracts the ~4 Hz envelope
modulation per band, weights and combines it, and returns the overall F (vacil)
plus the specific fluctuation strength over the Bark axis and the time-dependent
trace.
from phonometry import psychoacoustics
res = psychoacoustics.fluctuation_strength(x, fs)print(res.fluctuation_strength) # vacilres.plot() # specific fluctuation strength F′(z) over the Bark axis (needs matplotlib)Show the code for this figure
import matplotlib.pyplot as pltimport numpy as npfrom phonometry import psychoacoustics
# The reference-like stimulus: a 1 kHz tone at 70 dB SPL, 100 % amplitude# modulated at 4 Hz, where the sensation peaks.fs = 48000t = np.arange(int(2.0 * fs)) / fsam = (1.0 + np.sin(2 * np.pi * 4.0 * t)) * np.sin(2 * np.pi * 1000 * t)am = am / np.sqrt(np.mean(am ** 2)) * 2e-5 * 10 ** (70 / 20)res = psychoacoustics.fluctuation_strength(am, float(fs))print(round(res.fluctuation_strength, 2)) # 1.09 vacil
# One line: the specific fluctuation strength over the Bark axis.res.plot()plt.show()
# Or draw f'(z) by hand from the arrays the result carries:fig, ax = plt.subplots()ax.fill_between(res.bark_axis, res.specific, alpha=0.3)ax.plot(res.bark_axis, res.specific)ax.set_xlabel("Critical-band rate z [Bark]")ax.set_ylabel("Specific fluctuation strength [vacil/Bark]")plt.show()The sensation stays where the modulated energy is, in the critical bands around the carrier, which is exactly why the closed form of §3.1 and the signal model diverge for broadband modulated noise: there the modulation is spread over the whole Bark axis and the band-by-band model accumulates more of it than the single closed form allows.
What this guide covers
Section titled “What this guide covers”Covered. Fastl & Zwicker’s Psychoacoustics: Facts and Models gives the
exact PA model, Eqs 16.2-16.4 (origin Widmann 1992), run by
psychoacoustic_annoyance. It also gives the closed form for AM broadband
noise, Eq. 10.2, run by fluctuation_strength_am_noise. The Osses et al.
(2016) signal model for fluctuation strength runs as fluctuation_strength,
cross-checked against its Table 1 literature values and the SQAT reference.
psychoacoustic_annoyance_from_signal derives the four inputs from a signal
(ISO 532-1 Zwicker N5, DIN 45692 S, ECMA-418-2 R) and combines them
with the exact model.
Not covered. The Osses 2016 model’s accuracy for FM tones is explicitly
not pursued. Only AM stimuli are validated here. The front-end also departs
from the paper’s exact framing (2 s frames, 90 % overlap, absolute-threshold
gating). As a result, a steady 1 kHz tone reads about 0.09 vacil instead of
0, and steady broadband noise reads about 0.4 vacil. For AM broadband noise,
quote fluctuation_strength_am_noise (§3.1) instead of
fluctuation_strength, which overshoots that stimulus. The normative
Sottek-model fluctuation strength of ECMA-418-2 Clause 9 is not implemented
on this page: it lives in
Sound Quality Metrics.
See also
Section titled “See also”- API reference:
psychoacoustics.psychoacoustic_annoyanceandpsychoacoustics.fluctuation_strength.
References
Section titled “References”- Fastl, H., & Zwicker, E. (2007). Psychoacoustics: Facts and models (3rd ed.). Springer. https://doi.org/10.1007/978-3-540-68888-4The source of the psychoacoustic-annoyance model of section 2 (Eqs 16.2-16.4, chapter 16; origin Widmann 1992) and of the closed-form fluctuation strength for AM broadband noise of section 3.1 (Eq. 10.2, chapter 10).
- Felix Greco, G., Merino-Martínez, R., Osses, A., & Lotinga, M. J. B. (2025). SQAT: A sound quality analysis toolbox for MATLAB. GitHub. https://doi.org/10.5281/zenodo.7934709The open MATLAB reference (open-source software) used as the numeric oracle for the fluctuation-strength cross-checks on this page.
- Osses Vecchi, A., García León, R., & Kohlrausch, A. (2016). Modelling the sensation of fluctuation strength. Proceedings of Meetings on Acoustics, 28, 050005. https://doi.org/10.1121/2.0000410The fluctuation-strength signal model implemented in section 3.2 (presented at ICA 2016; clean-room, with no numeric standard, calibrated to 1 vacil at the reference AM tone), including the Table 1 literature values used as its cross-check.