amads.time.swing#

This module implements various functions useful for analyzing swing in jazz and other genres.

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

Author:

Huw Cheston (2025)

amads.time.swing.beat_upbeat_ratio(beats, upbeats, log2=False, bounded=False, lower_bound=0.25, upper_bound=4.0) list[float][source]#

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 0.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, optional) – If True, computes the log base 2 of BUR values, as used in [2]. Defaults to False.

  • bounded (bool, optional) – If True, filters out BUR values outside the specified range. Defaults to False.

  • lower_bound (float, optional) – Lower boundary for filtering BUR values. Defaults to 0.25 (\(log_2\) -2).

  • upper_bound (float, optional) – Upper boundary for filtering BUR values. Defaults to 4.0 (\(log_2\) 2).

Returns:

A list of the calculated BUR values.

Return type:

list[float]

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]
amads.time.swing.match_beats_and_upbeats(beats, upbeats) ndarray[source]#

Iterates over consecutive beats and creates an array of [[beat1, upbeat, beat2], [beat2, upbeat, beat3]]

Parameters:
  • beats (ndarray)

  • upbeats (ndarray)

Return type:

ndarray

amads.time.swing.mean_bur(beats, upbeats, **kwargs) float[source]#

Calculates mean BUR (or \(log_2\) BUR) given a list of beats and upbeats

Parameters:
  • beats (Iterable[float])

  • upbeats (Iterable[float])

Return type:

float

amads.time.swing.std_bur(beats, upbeats, **kwargs) float[source]#

Calculates standard deviation BUR (or \(log_2\) BUR) given a list of beats and upbeats

Parameters:
  • beats (Iterable[float])

  • upbeats (Iterable[float])

Return type:

float