room.spatial_decay
Spatial sound distribution curves in workrooms (ISO 14257:2001).
A workroom is not a reverberation room and it is not a free field. Put a known source in it, walk away from it with a meter, and the level falls off somewhere between the 6 dB per distance doubling of a free field and the nothing at all of a perfectly diffuse room. That curve is what this standard measures, and the two numbers it derives from it are what a room is judged by:
- , the rate of spatial decay per distance doubling, which says how much quieter it gets by walking away, and
- , the excess of sound pressure level, which says how much louder the room is than a free field would have been.
The quantity everything is built on is the sound distribution value, the level at a point less the sound power level of the source that produced it, so that the curve belongs to the room and not to the source:
The reference curve is the same quantity in a free field, which is the inverse square law written as a level:
with = 1 m. The two derived quantities are a least-squares slope over a range of positions,
with , and the difference from the reference curve,
averaged over a distance range by Equation (7) or read off the regression line at one conventional distance by Equation (8).
The 0,3 of Equation (5). The slope of a least-squares fit of
against is a rate per decade; a doubling is of a
decade, which is 0,301 03. The clause prints 0,3, and that is what
DECADE_TO_DOUBLING carries, because the printed constant is what
reproduces the printed results. Equation (8) prints in full a page
later, so the two are not the same number in the same document; the difference
is 0,3 % of a slope and the errata registry records it.
Two spectra. A curve measured in octave bands can be collapsed onto the spectrum of a real machine by Equation (3), or onto the A-weighted pink noise of Table 1 by Equation (4), which is what a room gets judged by when nobody knows yet what will be installed in it.
The 6,2 of Equation (4). The constant is the energy sum of the
A-weighting curve over the six octaves, 6,23 dB, printed to one decimal, and it
is there so that a flat curve comes back unchanged. Table 1 prints the same
curve to one decimal weight by weight, and the six printed weights sum to
6,251 5 dB, so the printed equation returns a flat curve 0,05 dB high.
NORMALIZED_OFFSET_DB carries the printed 6,2 on the same rule as the
0,3 above: four printings print it and a reader checking against the page will
use it. Annex C was normalised exactly: its normalized column and its
Table C.10 land inside the printed rounding under Equation (3) with the Table 1
weights and one unit high in the last place under the printed constant, so
every value this module normalizes stands 0,05 dB above the annex. The errata
registry records it. Equation (3) with the Table 1 weights as the machine
spectrum is Equation (4) normalised exactly, for whoever needs the annex’s
reading.
Annex B. In a room whose own excess is small, what the measurement sees is partly the source’s own directivity and the reflection off the floor rather than the room. The annex corrects for that with a reference curve measured for that source in a free field over a reflecting plane, Equation (B.1), against the theoretical floor-reflected curve of Equations (B.2) to (B.4).
Read from BS EN ISO 14257:2001, which endorses ISO 14257:2001 without modification.
Auto-generated from the source docstrings by
scripts/generate_api_docs.py(make api-docs). Do not edit by hand.
ADJACENT_BAND_LIMIT_DB
Section titled “ADJACENT_BAND_LIMIT_DB”Constant (float).
ADJACENT_BAND_LIMIT_DB = 8.0BackgroundMarginCheck
Section titled “BackgroundMarginCheck”BackgroundMarginCheck( margins_db: NDArray[np.float64], needs_correction: NDArray[np.bool_], unusable: NDArray[np.bool_], satisfied: bool,)Whether the levels clear the background by what 5.1.4 asks.
Parameters
| Name | Description |
|---|---|
margins_db | The level of the source less the background at each position and band given, in decibels, in the shape they came in. |
needs_correction | True where the margin is under ISO14257_PREFERRED_SIGNAL_TO_BACKGROUND_DB and over ISO14257_MIN_SIGNAL_TO_BACKGROUND_DB, which is the window where the clause asks for the ISO 3744 background correction. |
unusable | True where the margin is at or under ISO14257_MIN_SIGNAL_TO_BACKGROUND_DB, which the clause offers no correction for. |
satisfied | True when every margin clears ISO14257_PREFERRED_SIGNAL_TO_BACKGROUND_DB, which is the only case that needs nothing done to it. |
check_background_margin
Section titled “check_background_margin”check_background_margin( levels_db: ArrayLike, background_levels_db: ArrayLike,) -> BackgroundMarginCheckDoes the source stand clear of the background? 5.1.4.
The clause asks for 10 dB at every position and in every octave band the
curve is measured over. Between 10 dB and 6 dB it asks for the background
correction of ISO 3744 (phonometry.emission.background_correction)
before the levels are used; at 6 dB or less it asks for neither, because
there is no longer a source level to correct towards.
The verdict is returned rather than applied: correcting the levels here
would change a measured number behind the caller’s back, and the correction
the clause names belongs to the standard that prints it. A margin under
10 dB anywhere also emits SpatialDecayWarning, so a curve computed
from levels nobody checked says so on the way past.
One octave band at a time, as every other function of clause 6 takes its positions: the clause asks the same 10 dB of every band, and a curve is read band by band.
Parameters
| Name | Description |
|---|---|
levels_db | with the test source running, in decibels, one value per measured position of one octave band. |
background_levels_db | The background at the same positions, in decibels, as a scalar or one value per position. |
Returns: The verdict, as a BackgroundMarginCheck.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that are not finite or do not match position for position. |
corrected_distribution_value
Section titled “corrected_distribution_value”corrected_distribution_value( distribution_values_db: ArrayLike, measured_reference_db: ArrayLike, distances_m: ArrayLike, *, source_height_m: float = 0.0, path_height_m: float | None = None,) -> NDArray[np.float64]The Annex B correction for the source’s own curve, Equation (B.1).
What the annex does is swap one reference curve for another: it takes the source’s measured free-field-over-a-reflecting-plane curve out of the measurement and puts the theoretical one back, so that what is left is the room. It matters where the room’s own excess is small, which is where the source’s directivity and the floor reflection are a large part of what the meter saw.
Parameters
| Name | Description |
|---|---|
distribution_values_db | in the room, in decibels. |
measured_reference_db | measured for this source over a reflecting plane, in decibels. |
distances_m | at each position, in metres. |
source_height_m | , in metres. |
path_height_m | , in metres. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that do not match position for position, or a correction that leaves no energy at all. |
DECADE_TO_DOUBLING
Section titled “DECADE_TO_DOUBLING”Constant (float).
DECADE_TO_DOUBLING = 0.3distance_region
Section titled “distance_region”distance_region( distance_m: float, *, near_limit_m: float = 5.0, far_limit_m: float = 16.0,) -> strWhich of the three regions of 6.2 a distance falls in.
The near region runs from 1 m to , the middle from to and the far one from out. The typical boundaries are 5 m and 16 m; other values may be used and are then recorded and reported, which is why they are arguments here.
Parameters
| Name | Description |
|---|---|
distance_m | The distance from the acoustical centre, in metres. |
near_limit_m | , in metres. |
far_limit_m | , in metres. |
Returns: "near", "middle" or "far".
Raises
| Exception | When |
|---|---|
| ValueError | For a non-positive distance, boundaries that do not increase, a near boundary inside the first metre, which would leave the near region empty, or a distance inside that first metre, which the clause does not evaluate. |
EVALUATION_DISTANCES_M
Section titled “EVALUATION_DISTANCES_M”Constant (mapping).
EVALUATION_DISTANCES_M = {'near': 4.0, 'middle': 10.0, 'far': 30.0}floor_reference_value
Section titled “floor_reference_value”floor_reference_value( distances_m: ArrayLike, *, source_height_m: float = 0.0, path_height_m: float | None = None,) -> NDArray[np.float64]The reference curve over a reflecting plane, Equations (B.2) to (B.4).
With the microphone path at the source height the product becomes , which is Equation (B.3); with the source on the floor the whole bracket becomes 2 and the correction is the 3 dB of Equation (B.4), the free field folded into a half space.
Parameters
| Name | Description |
|---|---|
distances_m | at each position, in metres. |
source_height_m | , in metres; zero for a source on the floor. |
path_height_m | , in metres; omit it for a path at the source height. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For a distance that is not strictly positive or a negative height. |
FREE_FIELD_OFFSET_DB
Section titled “FREE_FIELD_OFFSET_DB”Constant (float).
FREE_FIELD_OFFSET_DB = 11.0ISO14257_MIN_SIGNAL_TO_BACKGROUND_DB
Section titled “ISO14257_MIN_SIGNAL_TO_BACKGROUND_DB”Constant (float).
ISO14257_MIN_SIGNAL_TO_BACKGROUND_DB = 6.0ISO14257_PREFERRED_SIGNAL_TO_BACKGROUND_DB
Section titled “ISO14257_PREFERRED_SIGNAL_TO_BACKGROUND_DB”Constant (float).
ISO14257_PREFERRED_SIGNAL_TO_BACKGROUND_DB = 10.0ISO14257_REFERENCE_DISTANCE_M
Section titled “ISO14257_REFERENCE_DISTANCE_M”Constant (float).
ISO14257_REFERENCE_DISTANCE_M = 1.0level_excess
Section titled “level_excess”level_excess( distribution_values_db: ArrayLike, distances_m: ArrayLike,) -> NDArray[np.float64]The excess over a free field at each position, Equation (6).
Parameters
| Name | Description |
|---|---|
distribution_values_db | at each position, in decibels. |
distances_m | at each position, in metres. |
Returns: at each position, in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that do not match position for position. |
level_excess_at
Section titled “level_excess_at”level_excess_at( distribution_values_db: ArrayLike, distances_m: ArrayLike, distance_m: float,) -> floatThe excess read off the regression line at one distance, Equation (8).
This is the height of the fitted line over the free-field line at a
conventional distance: 4 m for the near region, 10 m for the middle one and
30 m for the far one (EVALUATION_DISTANCES_M). Unlike Equation (7)
it does not average the measured points, it reads the line, so a single
outlying position moves it much less.
Note that the clause divides by in full here while Equation (5) multiplies by the rounded 0,3; the two constants differ by 0,3 % and the errata registry records it.
Parameters
| Name | Description |
|---|---|
distribution_values_db | at the positions of the range, in decibels. |
distances_m | at the same positions, in metres. |
distance_m | , the distance to read at, in metres. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that do not match, fewer than two positions, or a non-positive distance. |
MAX_DIRECTIVITY_INDEX_DB
Section titled “MAX_DIRECTIVITY_INDEX_DB”Constant (float).
MAX_DIRECTIVITY_INDEX_DB = 8.0mean_level_excess
Section titled “mean_level_excess”mean_level_excess( distribution_values_db: ArrayLike, distances_m: ArrayLike,) -> floatThe excess averaged over a distance range, Equation (7).
It is the trapezoidal mean of the excess against the logarithm of the distance, which is the axis the curve is drawn on, so a position twice as far weighs the same as one twice as near rather than twice as much.
Parameters
| Name | Description |
|---|---|
distribution_values_db | at the positions of the range, in decibels. |
distances_m | at the same positions, in metres, in increasing order. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that do not match, fewer than two positions, or distances that do not increase. |
MIN_SOURCE_TO_WALL_M
Section titled “MIN_SOURCE_TO_WALL_M”Constant (float).
MIN_SOURCE_TO_WALL_M = 3.0NEAR_REGION_START_M
Section titled “NEAR_REGION_START_M”Constant (float).
NEAR_REGION_START_M = 1.0normalized_distribution_value
Section titled “normalized_distribution_value”normalized_distribution_value( distribution_values_db: ArrayLike, *, frequencies: ArrayLike | None = None,) -> floatThe curve collapsed onto A-weighted pink noise, Equation (4).
with from Table 1. It is Equation (3) with one spectrum fixed, and 4.2.3 says why that spectrum is a normalisation and not an average industrial machine: the spectra met in practice are too varied for any average to mean anything.
The 6,2 dB is the energy sum of the A-weighting curve printed to one
decimal, and the six printed weights of Table 1 sum to 6,251 5 dB, so the
printed equation returns a flat curve 0,05 dB high. It is used as printed:
the result is what a hand evaluation of the printed equation gives, which
is 0,05 dB above Annex C, normalised exactly (see the errata registry). For
the exact normalisation, which returns a flat curve unchanged, call
spectrum_distribution_value with the values of
PINK_NOISE_WEIGHTS_DB as the machine spectrum.
Parameters
| Name | Description |
|---|---|
distribution_values_db | in each band, in decibels, in the order of SPATIAL_DECAY_BANDS_HZ unless frequencies says otherwise. |
frequencies | The nominal octave centres the values belong to, in hertz. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For a count that is not the six bands of Table 1, or a frequency the table does not name. |
NORMALIZED_OFFSET_DB
Section titled “NORMALIZED_OFFSET_DB”Constant (float).
NORMALIZED_OFFSET_DB = 6.2OMNIDIRECTIONAL_RAMP_HZ
Section titled “OMNIDIRECTIONAL_RAMP_HZ”Constant (tuple).
OMNIDIRECTIONAL_RAMP_HZ = (630.0, 1000.0)OMNIDIRECTIONAL_TOLERANCE_DB
Section titled “OMNIDIRECTIONAL_TOLERANCE_DB”Constant (tuple).
OMNIDIRECTIONAL_TOLERANCE_DB = (2.0, 8.0)omnidirectionality_tolerance_db
Section titled “omnidirectionality_tolerance_db”omnidirectionality_tolerance_db(frequency_hz: float) -> floatThe directivity band a qualifying source stays inside, A.1.
The clause states the tolerance in three pieces: +/- 2 dB in the
one-third-octave bands from 100 Hz to 630 Hz, a linear increase to
+/- 8 dB between 630 Hz and 1 kHz, and +/- 8 dB from 1 kHz to
5 kHz. The increase is taken here across the three one-third-octave bands
that span it, so 800 Hz is the midpoint at 5 dB; the clause says “linearly”
without saying linear in what, and the band index is the only reading on
which the two endpoints land on printed bands.
Parameters
| Name | Description |
|---|---|
frequency_hz | The one-third-octave centre, in hertz. |
Returns: The largest absolute directivity index allowed, in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For a non-positive frequency. |
PINK_NOISE_WEIGHTS_DB
Section titled “PINK_NOISE_WEIGHTS_DB”Constant (mapping).
PINK_NOISE_WEIGHTS_DB = {125.0: -16.1, 250.0: -8.6, 500.0: -3.2, 1000.0: 0.0, 2000.0: 1.2, 4000.0: 1.0}PREFERRED_MIDDLE_LIMIT_M
Section titled “PREFERRED_MIDDLE_LIMIT_M”Constant (float).
PREFERRED_MIDDLE_LIMIT_M = 24.0reference_distribution_value
Section titled “reference_distribution_value”reference_distribution_value(distances_m: ArrayLike) -> NDArray[np.float64]The free-field reference curve, Equation (2).
The clause prints both forms and they are the same number to within the rounding of the 11: is 10,99. The printed 11 is what is used here, because it is the curve the standard draws in its own figures.
Parameters
| Name | Description |
|---|---|
distances_m | at each position, in metres. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For a distance that is not strictly positive. |
sound_distribution_value
Section titled “sound_distribution_value”sound_distribution_value( levels_db: ArrayLike, sound_power_levels_db: ArrayLike,) -> NDArray[np.float64]The sound distribution value of a measured point, Equation (1).
Subtracting the source’s own sound power is what makes the curve a property of the room: run the test again with a louder source and every value comes back the same.
Parameters
| Name | Description |
|---|---|
levels_db | at each position, in decibels. |
sound_power_levels_db | of the source, in decibels, as a scalar or one value per position. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that are not finite or do not broadcast. |
SOURCE_ON_FLOOR_HEIGHT_M
Section titled “SOURCE_ON_FLOOR_HEIGHT_M”Constant (float).
SOURCE_ON_FLOOR_HEIGHT_M = 0.5SPATIAL_DECAY_BANDS_HZ
Section titled “SPATIAL_DECAY_BANDS_HZ”Constant (tuple).
SPATIAL_DECAY_BANDS_HZ = (125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0)spatial_decay_curve
Section titled “spatial_decay_curve”spatial_decay_curve( distribution_values_db: ArrayLike, distances_m: ArrayLike, *, near_limit_m: float = 5.0, far_limit_m: float = 16.0, region: str = 'middle', band_hz: float | None = None,) -> SpatialDecayResultThe curve of one region with its two descriptors, clause 6.
Parameters
| Name | Description |
|---|---|
distribution_values_db | at every measured position, in decibels, over the whole path. |
distances_m | at the same positions, in metres, in increasing order. |
near_limit_m | of 6.2, in metres. |
far_limit_m | of 6.2, in metres. |
region | "near", "middle", "far" or "whole". |
band_hz | The octave centre the curve belongs to, in hertz. |
Returns: The curve and its descriptors, as a SpatialDecayResult.
Raises
| Exception | When |
|---|---|
| ValueError | For an unknown region, inputs that do not match, or a region holding fewer than two measured positions. |
spatial_decay_rate
Section titled “spatial_decay_rate”spatial_decay_rate( distribution_values_db: ArrayLike, distances_m: ArrayLike,) -> floatThe rate of spatial decay per distance doubling, Equation (5).
A free field gives 6 dB, a perfectly diffuse room gives 0, and a real workroom sits between them: 4,6 dB in the middle range of the Annex C example, which is a large and moderately fitted shipyard hall.
The sign is the way round a reader expects: the regression slope is negative, so a room that gets quieter with distance returns a positive number of decibels per doubling.
Parameters
| Name | Description |
|---|---|
distribution_values_db | at the positions of the range, in decibels. |
distances_m | at the same positions, in metres. |
Returns: , in decibels per distance doubling.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that do not match position for position, fewer than two positions, or positions that are all at one distance. |
SpatialDecayResult
Section titled “SpatialDecayResult”SpatialDecayResult( distances_m: NDArray[np.float64], distribution_values_db: NDArray[np.float64], reference_values_db: NDArray[np.float64], level_excess_db: NDArray[np.float64], decay_rate_db: float, mean_excess_db: float, region: str, band_hz: float | None = None,)A spatial sound distribution curve and what clause 6 reads off it.
Parameters
| Name | Description |
|---|---|
distances_m | The distance of each microphone position from the acoustical centre of the source, in metres. |
distribution_values_db | at each position, in decibels. |
reference_values_db | at each position, in decibels. |
level_excess_db | at each position, in decibels. |
decay_rate_db | over the range, in decibels per distance doubling. |
mean_excess_db | over the range, in decibels. |
region | "near", "middle", "far" or "whole". |
band_hz | The nominal octave centre the curve belongs to, in hertz, or None for a curve that stands for a spectrum. |
SpatialDecayResult.plot()
Section titled “SpatialDecayResult.plot()”SpatialDecayResult.plot(ax: Axes | None = None, **kwargs: Any) -> AxesDraw the curve, the free-field reference and the fitted slope.
Parameters
| Name | Description |
|---|---|
ax | Axes to draw on; a new figure is made when omitted. |
kwargs | Passed to the renderer, including language. |
Returns: The axes drawn on.
SpatialDecayWarning
Section titled “SpatialDecayWarning”The measurement is outside a condition ISO 14257 states.
spectrum_distribution_value
Section titled “spectrum_distribution_value”spectrum_distribution_value( distribution_values_db: ArrayLike, machine_power_levels_db: ArrayLike,) -> floatThe curve collapsed onto one machine’s spectrum, Equation (3).
The octave-band curve says what the room does to each band; this says what the room does to one particular machine, which is the number a layout decision is made on.
Parameters
| Name | Description |
|---|---|
distribution_values_db | in each band, in decibels. |
machine_power_levels_db | of the machine in the same bands, in decibels. |
Returns: , in decibels.
Raises
| Exception | When |
|---|---|
| ValueError | For inputs that do not match band for band. |
STABILITY_TOLERANCE_DB
Section titled “STABILITY_TOLERANCE_DB”Constant (mapping).
STABILITY_TOLERANCE_DB = {(100.0, 160.0): 1.0, (200.0, 5000.0): 0.5}TYPICAL_FAR_LIMIT_M
Section titled “TYPICAL_FAR_LIMIT_M”Constant (float).
TYPICAL_FAR_LIMIT_M = 16.0TYPICAL_NEAR_LIMIT_M
Section titled “TYPICAL_NEAR_LIMIT_M”Constant (float).
TYPICAL_NEAR_LIMIT_M = 5.0