Laughter¶
Where laughter probably is, shipped as proposals because it was measured first.
Where laughter is in a recording, and nothing else about it.
Split the way _voice is split, and for the same reason: the model wrapper has no right
answer and cannot run in CI, so it is kept as thin as it can be, and the part with a right
answer is a separate function that is tested.
Six classes, not one. AudioSet splits laughter into Laughter, Baby laughter,
Giggle, Snicker, Belly laugh and Chuckle, chortle. Taking only the one called
Laughter silently discards the giggling and chuckling that a rehearsal is mostly made of.
Why a tagger here, when _voice argues against one. _voice rejected PANNs for
speech because a clip-level tag answers "is there speech in this minute", which is not the
question, and because dancers breathing came back as Snort, Gasp, Animal and Horse.
Both objections were about minute-long clips. Run at a two-second window on the six
laughter classes and measured against Finn Upham's 79 hand-coded annotations of this
project's corpus, it reaches ROC AUC 0.823 against a level baseline's 0.741, and 91
per cent precision in the top 5 per cent of windows. That is why laughter ships as
proposals a person confirms, and why speech does not ship from a tagger at all.
What this does not claim. It says where laughter probably is. It does not say who laughed, why, or whether it was shared --- all of which a human coded for the corpus this was validated on, and none of which is recoverable from a clip-level score.
Span assembly is _voice.spans_from_probabilities, not a second copy: it already closes
short gaps before dropping short bursts, and the order matters.
laughter_score ¶
laughter_score(clipwise_output)
One laughter score per clip, from a PANNs clipwise output.
The strongest laughter class, not their sum. A sum lets six lukewarm classes outvote
one confident class, and the six are not independent: a real belly laugh raises
Laughter and Belly laugh together, and adding them counts the same event twice.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
clipwise_output
|
Array of shape (n_clips, 527), as PANNs |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: One score per clip, in [0, 1]. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the second dimension is not 527. |
Source code in musicalgestures/_laughter.py
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | |
laughter_segments ¶
laughter_segments(audio, sr=32000, win_s=2.0, hop_s=1.0, threshold=0.5, min_laughter_s=0.5, min_silence_s=0.5, device='cpu', checkpoint_path=None)
Spans where laughter is likely, for a person to confirm or delete.
PANNs is an optional dependency, loaded here and nowhere else so that importing this module costs nothing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
audio
|
Mono audio, one dimension, sampled at |
required | |
sr
|
int
|
Sample rate. PANNs wants 32000. Defaults to 32000. |
32000
|
win_s
|
float
|
Analysis window in seconds. Defaults to 2.0, at which the detector was validated. Longer windows were what made the earlier probe on this corpus useless. |
2.0
|
hop_s
|
float
|
Step between windows. Defaults to 1.0. |
1.0
|
threshold
|
float
|
Score above which a window counts as laughter. Defaults to 0.5. Raise it for proposals somebody has to review: at the corpus's top 5 per cent the precision was 0.91, at the top 10 per cent it was 0.71. |
0.5
|
min_laughter_s
|
float
|
Spans shorter than this are dropped. Defaults to 0.5. |
0.5
|
min_silence_s
|
float
|
Gaps shorter than this are closed first. Defaults to 0.5. |
0.5
|
device
|
str
|
|
'cpu'
|
checkpoint_path
|
Passed to PANNs, or None for its default. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
Actions with |
|
|
|
||
|
threshold somebody else chose. |
Source code in musicalgestures/_laughter.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | |