<!-- canonical: https://jmrplens.github.io/phonometry/reference/api/rooms/crowd-noise/ -->
Source: https://jmrplens.github.io/phonometry/reference/api/rooms/crowd-noise/

Crowd self-noise in a restaurant: the cocktail-party equilibrium.

In a room where the only source of noise is the occupants themselves, the
background against which each conversation has to be understood is generated by
the *other* conversations. Long (*Architectural Acoustics* 2nd ed., Chapter 17,
Equations (17.50) to (17.54)) writes the two competing levels at a listener:

* the **signal**, the direct field of the person across the table
  (Equation (17.50)),
  $L_p^{\text{signal}} = L_W + 10 \log_{10}[Q / (4 \pi r^2)]$;

* the **noise**, the reverberant field built up by `N` simultaneous talkers
  spread over the room (Equation (17.51)),
  $L_p^{\text{noise}} = L_W + 10 \log_{10} N + 10 \log_{10}[4 / (N A_{\text{tab}})]$;

where `Lw` is the sound power level of one talker (about 70 dB for normal
conversation), `Q` the talker's directivity factor (about 2 in the forward
direction), `r` the talker-to-listener distance and `A_tab` the equivalent
absorption area *per occupied table*, so that $N A_{\text{tab}}$ is the
room's total
absorption. Their difference is the speech-to-noise ratio (Equation (17.52)):

$$
L_\mathrm{SN} = 10 \log_{10}\!\left[ \frac{Q}{4 \pi r^2} \right] + 10 \log_{10}\!\left[ \frac{A_{\text{tab}}}{4} \right]
$$

which is independent of the talker's power and of the number of talkers: adding
a table adds both a talker and its share of absorption. What decides whether a
restaurant works is therefore the *absorption per table*, not its total
absorption. Requiring $L_\mathrm{SN} > -6$ dB for adequate cross-table
communication
at a separation `rs`, and $L_\mathrm{SN} < -9$ dB for privacy between tables
a distance `rt` apart, turns into a pair of design bounds
(Equations (17.53) and (17.54)):

$$
A_{\text{tab}} > 16 \pi\, 10^{-0.6}\, r_s^2 / Q \approx 6.31\, r_s^2 \quad (Q = 2)
$$

$$
A_{\text{tab}} < 16 \pi\, 10^{-0.9}\, r_t^2 / Q \approx 3.16\, r_t^2 \quad (Q = 2)
$$

:::note
Long prints the first constant as `6.33`; the closed form with the same
$Q = 2$ and `-6 dB` that yield his second constant `3.16` gives
`6.31`, which is also what his own conversion of the result ("6.3 or more
square metres (68 sq ft)") implies (see `docs/ERRATA.md`). This module
computes both constants from [`speech_to_noise_ratio`](/phonometry/reference/api/rooms/crowd-noise/#speech_to_noise_ratio), so they stay
mutually consistent.

His prose also puts the direct field at an adjacent table 3 m away at
"about 54 dB", where [`speech_direct_level`](/phonometry/reference/api/rooms/crowd-noise/#speech_direct_level) with the same
$Q = 2$
and $L_W = 70$ dB gives 52.5 dB. That one is left as printed rather
than
reconciled, because the intended reading cannot be established from the
book; it is recorded under the non-errata notes of `docs/ERRATA.md`.
:::

The **Lombard reflex** (talkers raising their voices as the background grows)
is deliberately *not* modelled: it cancels out of `L_SN` as long as everyone
raises their voice equally, and Long uses the model in exactly that way, as the
explanation of why the level spirals upward in a hard room rather than as a
predictor of the final level.

This is a *design* model for the self-generated noise of an occupied room. The
measurement standard for the spatial decay of speech in an open-plan office is
ISO 3382-3, implemented separately in [`phonometry.room.open_plan`](/phonometry/reference/api/rooms/open-plan/): that
one derives `D2,S`, the distraction distance and the privacy distance from
measured levels along a line of workstations, and predicts nothing.

> Auto-generated from the source docstrings by `scripts/generate_api_docs.py` (`make api-docs`). Do not edit by hand.

## absorption_per_table

```python
absorption_per_table(
    distance: ArrayLike,
    speech_to_noise: float,
    *,
    directivity: float = 2.0,
) -> np.ndarray | float
```

Absorption per table giving a chosen `L_SN` (inverse of (17.52)).

$A_{\text{tab}} = 16 \pi r^2\, 10^{L_\mathrm{SN}/10} / Q$. With
$L_\mathrm{SN} = -6$ dB this is
Long's communication bound (Equation (17.53)), with `-9 dB` his privacy
bound (Equation (17.54)).

**Parameters**

| Name | Description |
| :--- | :--- |
| `distance` | Separation `r`, m: the cross-table distance `rs` for the communication bound, the table-to-table distance `rt` for the privacy bound. |
| `speech_to_noise` | Target speech-to-noise ratio `L_SN`, dB. |
| `directivity` | Talker directivity factor `Q`. |

**Returns:** The equivalent absorption area per table `A_tab`, m2.

## COMMUNICATION_SNR

*Constant* (`float`).

```python
COMMUNICATION_SNR = -6.0
```

## crowd_noise

```python
crowd_noise(
    absorption_areas: ArrayLike,
    *,
    talkers: ArrayLike | None = None,
    distance: float = 1.2,
    sound_power_level: float = 70.0,
    directivity: float = 2.0,
) -> CrowdNoiseResult
```

Self-noise of an occupied room versus occupancy (Long 17.50-17.52).

Evaluates Equation (17.51) over an occupancy axis for each of the supplied
total absorption areas, together with the direct-field signal of
Equation (17.50) at the listener across the table.

**Parameters**

| Name | Description |
| :--- | :--- |
| `absorption_areas` | Total equivalent absorption areas `A` of the room to compare, m2 (scalar or 1-D). |
| `talkers` | Occupancy axis `N`, the number of simultaneous talkers; default the integers `1..20`. |
| `distance` | Talker-to-listener distance `r`, m (default 1.2 m, Long's cross-table distance). |
| `sound_power_level` | Sound power level `Lw` of one talker, dB re 1 pW (default [`NORMAL_VOICE_POWER_LEVEL`](/phonometry/reference/api/rooms/crowd-noise/#normal_voice_power_level)). |
| `directivity` | Talker directivity factor `Q` (default [`TALKER_DIRECTIVITY`](/phonometry/reference/api/rooms/crowd-noise/#talker_directivity)). |

**Returns:** A [`CrowdNoiseResult`](/phonometry/reference/api/rooms/crowd-noise/#crowdnoiseresult).

## crowd_noise_level

```python
crowd_noise_level(
    talkers: ArrayLike,
    absorption_area: ArrayLike,
    *,
    sound_power_level: float = 70.0,
) -> np.ndarray | float
```

Reverberant level of `N` simultaneous talkers (Long Equation (17.51)).

$L_p = L_W + 10 \log_{10} N + 10 \log_{10}(4 / A)$ with the room's
total equivalent absorption area `A`
($= N A_{\text{tab}}$ when the absorption is
counted per occupied table).

**Parameters**

| Name | Description |
| :--- | :--- |
| `talkers` | Number `N` of simultaneous talkers (scalar or array, at least 1). |
| `absorption_area` | Total equivalent absorption area `A` of the room, metric sabins (m2) (scalar or array). |
| `sound_power_level` | Sound power level `Lw` of one talker, dB re 1 pW (default [`NORMAL_VOICE_POWER_LEVEL`](/phonometry/reference/api/rooms/crowd-noise/#normal_voice_power_level)). |

**Returns:** The self-generated reverberant level, dB.

## CrowdNoiseResult

```python
CrowdNoiseResult(
    talkers: np.ndarray,
    absorption_areas: np.ndarray,
    levels: np.ndarray,
    signal_level: float,
    distance: float,
    sound_power_level: float,
    directivity: float,
    communication_level: float,
)
```

Self-generated noise of an occupied room versus occupancy and absorption.

**Attributes**

| Name | Description |
| :--- | :--- |
| `talkers` | Number of simultaneous talkers on the occupancy axis. |
| `absorption_areas` | Total room absorption areas compared, m2, one per row of `levels`. |
| `levels` | Reverberant self-noise level, dB, shaped `(len(absorption_areas), len(talkers))`. |
| `signal_level` | Direct-field level of the talker across the table, dB. |
| `distance` | Talker-to-listener distance `r`, m. |
| `sound_power_level` | Sound power level of one talker, dB re 1 pW. |
| `directivity` | Talker directivity factor `Q`. |
| `communication_level` | Noise level at which the speech-to-noise ratio falls to [`COMMUNICATION_SNR`](/phonometry/reference/api/rooms/crowd-noise/#communication_snr), dB: above it, cross-table conversation stops working. |

### CrowdNoiseResult.plot()

```python
CrowdNoiseResult.plot(
    ax: Axes | None = None,
    *,
    language: str = 'en',
    **kwargs: Any,
) -> Axes
```

Plot the self-noise level against occupancy, one curve per absorption.

The direct-field level of the talker across the table and the
speech-to-noise limit of Equation (17.53) are drawn as references, so
the crossing point reads directly as the occupancy at which the room
stops working. Requires matplotlib
(`pip install phonometry[plot]`).

### CrowdNoiseResult.speech_to_noise()

```python
CrowdNoiseResult.speech_to_noise() -> np.ndarray
```

Speech-to-noise ratio for every point of `levels`, dB.

## NORMAL_VOICE_POWER_LEVEL

*Constant* (`float`).

```python
NORMAL_VOICE_POWER_LEVEL = 70.0
```

## PRIVACY_SNR

*Constant* (`float`).

```python
PRIVACY_SNR = -9.0
```

## speech_direct_level

```python
speech_direct_level(
    distance: ArrayLike,
    *,
    sound_power_level: float = 70.0,
    directivity: float = 2.0,
) -> np.ndarray | float
```

Direct-field level of one talker (Long Equation (17.50)).

$L_p = L_W + 10 \log_{10}[Q / (4 \pi r^2)]$, the signal a listener
across the table receives.

**Parameters**

| Name | Description |
| :--- | :--- |
| `distance` | Talker-to-listener distance `r`, m (scalar or array). |
| `sound_power_level` | Talker sound power level `Lw`, dB re 1 pW (default [`NORMAL_VOICE_POWER_LEVEL`](/phonometry/reference/api/rooms/crowd-noise/#normal_voice_power_level)). |
| `directivity` | Talker directivity factor `Q` (default [`TALKER_DIRECTIVITY`](/phonometry/reference/api/rooms/crowd-noise/#talker_directivity)). |

**Returns:** The direct-field sound pressure level, dB.

## speech_to_noise_ratio

```python
speech_to_noise_ratio(
    distance: ArrayLike,
    absorption_per_table: ArrayLike,
    *,
    directivity: float = 2.0,
) -> np.ndarray | float
```

Speech-to-noise ratio across a table (Long Equation (17.52)).

$L_\mathrm{SN} = 10 \log_{10}[Q / (4 \pi r^2)] + 10 \log_{10}[A_{\text{tab}} / 4]$, the difference
between Equations (17.50) and (17.51). Neither the talker's power nor the
number of talkers appears: a busier room brings its own absorption with it.

**Parameters**

| Name | Description |
| :--- | :--- |
| `distance` | Talker-to-listener distance `r`, m. |
| `absorption_per_table` | Equivalent absorption area per occupied table `A_tab`, m2. |
| `directivity` | Talker directivity factor `Q`. |

**Returns:** The speech-to-noise ratio, dB.

## TALKER_DIRECTIVITY

*Constant* (`float`).

```python
TALKER_DIRECTIVITY = 2.0
```
