Swing
swing
¶
This module implements various functions useful for analyzing swing in jazz and other genres.
Author: Huw Cheston (2025)
References
-
Benadon, F. (2006). Slicing the Beat: Jazz Eighth-Notes as Expressive Microrhythm. Ethnomusicology, 50(1), 73–98. https://doi.org/10.2307/20174424
-
Corcoran, C., & Frieler, K. (2021). Playing It Straight: Analyzing Jazz Soloists’ Swing Eighth-Note Distributions with the Weimar Jazz Database. Music Perception, 38(4), 372–385. https://doi.org/10.1525/mp.2021.38.4.372
beat_upbeat_ratio
¶
beat_upbeat_ratio(
beats: Iterable[float],
upbeats: Iterable[float],
log2: bool = False,
bounded: bool = False,
lower_bound: float = LOW_BUR,
upper_bound: float = HIGH_BUR,
) -> list[float]
Extracts beat-upbeat ratio (BUR) values from an array of beats and upbeats.
The beat-upbeat ratio (BUR) is used to analyze the amount of “swing” in two consecutive eighth-note beat durations. It is calculated by dividing the duration of the first (“long”) eighth-note beat by the duration of the second (“short”) eighth-note beat. A BUR value of 2 represents “perfect” swing (e.g., a triplet quarter note followed by a triplet eighth note), while a BUR of 1 represents “even” eighth-note durations.
The formula for BUR is:
$\text{BUR} = \frac{t_{a,b} - t_{a}}{t_{b} - t_{a,b}}$, where
$t_a$ is the beat at position $a$, $t_b$ is the beat at position $b$, and $t_{a,b}$ is the single upbeat between beats $a$ and $b$.
The function takes two iterables of timestamps: beats and upbeats.
Both lists should be unique, and missing values should not be present.
The function returns an array of BUR values with a size of
len(beats) - 1. If multiple upbeats are found between two
consecutive beats or if no upbeat is found, the BUR for those
beats will be omitted and the corresponding value will be None.
Additionally, the function can calculate the $log_2$ of the
BUR values, where a value of 1.0 corresponds to “triplet” swing.
This can be enabled by setting log2=True. The values can also
be filtered to remove outliers by setting bounded=True, with
the default values for the boundaries coming from Corcoran &
Frieler (2021).
Parameters:
-
beats(Iterable[float]) –An array of beat timestamps. Should not overlap with
upbeats. -
upbeats(Iterable[float]) –An array of upbeat timestamps.
-
log2(bool, default:False) –If True, computes the log base 2 of BUR values, as used in [2]. Defaults to False.
-
bounded(bool, default:False) –If True, filters out BUR values outside the specified range. Defaults to False.
-
lower_bound(float, default:LOW_BUR) –Lower boundary for filtering BUR values. Defaults to 0.25 ($log_2$ value of -2).
-
upper_bound(float, default:HIGH_BUR) –Upper boundary for filtering BUR values. Defaults to 4.0 ($log_2$ value of 2).
Returns:
-
list[float]–A list of the calculated BUR values.
Examples:
>>> my_beats = [0., 1., 2., 3.]
>>> my_upbeats = [0.5, 1.75, 2.2]
>>> beat_upbeat_ratio(my_beats, my_upbeats)
[1., 3., 0.25]
>>> # Consecutive beats without a matching upbeat will be skipped.
>>> my_beats = [0., 1., 2., 3.]
>>> my_upbeats = [0.5, 2.2]
>>> beat_upbeat_ratio(my_beats, my_upbeats)
[1., None, 0.25]
>>> # Consecutive beats with multiple matching upbeats will be skipped.
>>> my_beats = [0., 1., 2., 3.]
>>> my_upbeats = [0.5, 1.5, 1.75, 1.8, 2.2]
>>> beat_upbeat_ratio(my_beats, my_upbeats)
[1., None, 0.25]
>>> # Filter out outlying values by setting `bounded=True`.
>>> my_beats = [0., 1., 2., 3.]
>>> my_upbeats = [0.5, 1.75, 2.99]
>>> beat_upbeat_ratio(my_beats, my_upbeats, bounded=True)
[1., 3., None]
Source code in amads/time/swing.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
mean_bur
¶
mean_bur(
beats: Iterable[float], upbeats: Iterable[float], **kwargs
) -> float
Calculates mean BUR (or $log_2$ BUR) given a list of beats and upbeats
Source code in amads/time/swing.py
156 157 158 159 160 161 162 163 164 165 | |
std_bur
¶
std_bur(
beats: Iterable[float], upbeats: Iterable[float], **kwargs
) -> float
Calculates standard deviation BUR (or $log_2$ BUR) given a list of beats and upbeats
Source code in amads/time/swing.py
168 169 170 171 172 | |
match_beats_and_upbeats
¶
match_beats_and_upbeats(beats: ndarray, upbeats: ndarray) -> ndarray
Iterates over consecutive beats and creates an array of [[beat1, upbeat, beat2], [beat2, upbeat, beat3]]
Source code in amads/time/swing.py
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | |