Harmonicity Metrics#
- compute_consonance(ratio, limit=1000)[source]#
Compute metric of consonance from a single ratio of frequencies in the form (a+b)/(a*b).
- Parameters:
ratio (float) – The ratio of frequencies.
limit (int, default=1000) – The maximum value of the denominator of the fraction representing the ratio.
- Returns:
cons (float) – The consonance value.
Examples
>>> compute_consonance(3/2, limit=1000) 0.8333333333333334 >>> compute_consonance(16/9, limit=1000) 0.1736111111111111
- euler(*numbers)[source]#
Euler’s “gradus suavitatis” (degree of sweetness) function Return the “degree of sweetness” of a musical interval or chord expressed as a ratio of frequencies a:b:c, according to Euler’s formula Greater values indicate more dissonance.
- Parameters:
*numbers (List or Array of int) – Frequencies
- Returns:
euler (int) – Euler Gradus Suavitatis.
Examples
>>> peaks = [3, 7, 13, 19] >>> euler(*peaks) 39 >>> peaks = [3, 9, 11, 27] >>> euler(*peaks) 17
- tenneyHeight(peaks, avg=True)[source]#
Tenney Height is a measure of inharmonicity calculated on two frequencies (a/b) reduced in their simplest form. It can also be called the log product complexity of a given interval. This function computes the Tenney Height pairwise across a list of peaks. Higher values represents higher dissonance.
- Parameters:
peaks (List (float)) – frequencies
avg (bool, default=True) – When set to True, all tenney heights are averaged.
- Returns:
tenney (float) – Tenney Height
Examples
>>> peaks = [3, 7, 13, 19] >>> tenneyHeight(peaks) 6.170342327181719 >>> peaks = [3, 9, 11, 27] >>> tenneyHeight(peaks) 4.371319977187242
- integral_tenneyHeight(peaks, avg=True)[source]#
Integral Tenney Height is a measure of inharmonicity calculated on a list of frequencies. It considers the prime factorization of the numerator and denominator of each interval, reflecting the complexity of the interval. Higher values represent higher dissonance.
- Parameters:
peaks (List (float)) – List of frequencies.
avg (bool, default=True) – When set to True, the average of Tenney Heights is returned.
- Returns:
tenney (float) – Integral Tenney Height.
Examples
>>> peaks = [3, 7, 13, 19] >>> integral_tenneyHeight(peaks) 12.28 >>> peaks = [3, 9, 11, 27] >>> integral_tenneyHeight(peaks) 8.49
- metric_denom(ratio)[source]#
Function that computes the denominator of the normalized ratio. Higher value represents higher dissonance.
- Parameters:
ratio (float) – frequency ratio
- Returns:
y (float) – denominator of the normalized ratio
Examples
>>> metric_denom(1.50) 2 >>> metric_denom(1.51) 100
- dyad_similarity(ratio)[source]#
This function computes the similarity between a dyad of frequencies and the natural harmonic series of their greatest common divisor. Higher value represents higher harmonicity. Implemented from Gill and Purves (2009)
- Parameters:
ratio (float) – frequency ratio
- Returns:
z (float) – dyad similarity
Examples
>>> dyad_similarity(3/2) 66.66666666666666 >>> dyad_similarity(16/9) 16.666666666666664
- sum_p_q(scale)[source]#
Calculate a metric for a scale. This is an estimate of scale consonance. It is derived from summing the numerators and denominators of the scale degrees.
Smaller values are more consonant.
- Parameters:
scale (List) – The scale.
- Returns:
dict – A dictionary with the metric value.
Notes
Note that this metric looks at the degrees of the scale, so it is somewhat tonic-focused. The similar metric
sum_p_q_for_all_intervals()
is similar, but it sums the numerator and denominator values for all distinct intervals within the scale.While the metric is numerically defined for ratios expressed as irrational or transcendental numbers, it is really only meaningful for scales with just degrees (ratios expressed as rational numbers).
Examples
>>> sum_p_q(create_pythagorean_scale()) {'sum_p_q': 3138}
- sum_distinct_intervals(scale)[source]#
Calculate a metric for a scale. This metric is an estimate of scale consonance. Numerically it is the number of distinct intervals within the scale (including all ratios and their inversions). Smaller values are more consonant.
- Parameters:
scale (List) – The scale.
- Returns:
dict – A dictionary with the metric value.
Examples
>>> sum_distinct_intervals(create_pythagorean_scale()) {'sum_distinct_intervals': 22}
- metric_3(scale)[source]#
Calculate a metric for a scale
- Parameters:
scale (List) – The scale.
- Returns:
dict – A dictionary with the metric value.
Notes
Metric 3 is an estimate of scale consonance. Given a ratio p/q, it is a heuristic given by the following:
\[\begin{align} m_3 &= \sum{\frac{1}{\frac{p-q}{q}}} \ &= \sum{\frac{q}{p-q}} \end{align}\]Smaller values are more consonant.
The summation takes place over all of the intervals in the scale. It does not form a set of distinct intervals.
- sum_p_q_for_all_intervals(scale)[source]#
Calculate a metric for a scale
- Parameters:
scale (List) – The scale.
- Returns:
dict – A dictionary with the metric value.
Notes
This metric is an estimate of scale consonance. It is formed by examining all unique intervals in the scale, and creating a numeric value based upon the summation of the numerators and denominators for all those intervals.
While the metric is numerically defined for ratios expressed as irrational or transcendental numbers, it is really only meaningful for scales with just degrees (ratios expressed as rational numbers).
Smaller values are more consonant.
- sum_q_for_all_intervals(scale)[source]#
Calculate a metric for a scale.
- Parameters:
scale (List) – The scale.
- Returns:
dict – A dictionary with the metric value.
Notes
This metric is an estimate of scale consonance. It is summation of the denominators of the normalized distinct ratios of the scale.
Smaller values are more consonant.
- ratios2harmsim(ratios)[source]#
Metric of harmonic similarity represents the degree of similarity between a tuning and the natural harmonic series. This function uses the dyad_similarity function on a set of ratios. Implemented from Gill and Purves (2009)
- Parameters:
ratios (List (float)) – list of frequency ratios (forming a tuning)
- Returns:
similarity (List (float)) – list of percentage of similarity for each ratios
Examples
>>> ratios = [3/2, 4/3, 16/9] >>> ratios2harmsim(ratios) array([66.66666667, 50. , 16.66666667])
References
Gill, K. Z., & Purves, D. (2009). A biological rationale for musical consonance. Proceedings of the National Academy of Sciences, 106(29), 12174-12179.
- tuning_cons_matrix(tuning, function, ratio_type='pos_harm')[source]#
This function gives a tuning metric corresponding to the averaged metric for each pairs of ratios
- Parameters:
tuning (List (float)) – List of tuning steps (classically between 1 (unison) and 2 (octave))
function (function) – {‘dyad_similarity’, ‘compute_consonance’, ‘metric_denom’}
ratio_type (str, default=’pos_harm’) –
- choice:
‘pos_harm’ : a/b when a>b
‘sub_harm’ : a/b when a<b
‘all’: pos_harm + sub_harm
- Returns:
metric_values (List) – list of the size of input corresponding to the averaged harmonicity between a step and all other steps.
metric_avg (float) – metric value averaged across all steps
full_matrix (List[List]) – full matrix [n, n] of metric values for each pair of ratios
Examples
>>> tuning = [1, 1.13, 1.25, 1.33, 1.5, 1.67, 1.75, 1.89] >>> function = dyad_similarity >>> tuning_cons_matrix(tuning, function, ratio_type="pos_harm") ([nan, 1.8761061946902655, 14.517994100294985, 8.079064918934504, 15.143364606205779, 10.567105885817467, 12.66150677394233, 10.398481038234042], 10.398481038234042)
>>> tuning = [1, 1.13, 1.25, 1.33, 1.5, 1.67, 1.75, 1.89] >>> function = compute_consonance >>> tuning_cons_matrix(tuning, function, ratio_type="pos_harm") ([nan, 0.018849557522123892, 0.1618997050147493, 0.08918417725730254, 0.17648067513917537, 0.1223854594889003, 0.1428532247343695, 0.11630349967694496], 0.11630349967694496)
- tuning_to_metrics(tuning, maxdenom=1000)[source]#
This function computes the tuning metrics of the PyTuning library (https://pytuning.readthedocs.io/en/0.7.2/metrics.html) and other tuning metrics
- Parameters:
tuning (List (float)) – List of ratios corresponding to tuning steps
maxdenom (int (default=1000)) – Maximum denominator of the fraction representing each tuning step.
- Returns:
tuning_metrics (dictionary) – keys correspond to metrics names
tuning_metrics_list (List (float)) – List of values corresponding to all computed metrics (in the same order as dictionary)
Examples
>>> tuning = [1, 1.13, 1.25, 1.33, 1.5, 1.67, 1.75, 1.89] >>> tuning_to_metrics(tuning, maxdenom=1000) {'sum_p_q': 1029, 'sum_distinct_intervals': 56, 'metric_3': 20.6720768749949, 'sum_p_q_for_all_intervals': 10794, 'sum_q_for_all_intervals': 5244, 'harm_sim': 31.14, 'matrix_harm_sim': 10.398481038234042, 'matrix_cons': 0.11630349967694496, 'matrix_denom': 83.64285714285714}
- timepoint_consonance(data, method='cons', limit=0.2, min_notes=3, graph=False, n_harm=5, delta_lim=20)[source]#
Function that keeps moments of consonance from multiple time series of peak frequencies. Can be used with the
biotuner.biotuner_object.compute_spectromorph()
function to compute timepoint consonance across the time series of spectral centroïd (or other spectromorphological metrics) derived from each Intrinsic Mode Function (IMF) using Empirical Mode Decomposition. This function can also be used of the instantaneous frequencies associated with each IMF.- Parameters:
data (List of lists (float)) – Axis 0 represents moments in time Axis 1 represents the sets of frequencies
method (str, default=’cons’) –
- ‘cons’:
will compute pairwise consonance between frequency peaks in the form of (a+b)/(a*b)
- ‘euler’:
will compute Euler’s gradus suavitatis
- ‘harmsim’:
will compute harmonic similarity using dyad_similarity function.
limit (float, default=0.2) –
limit of consonance under which the set of frequencies are not retained
- When method = ‘cons’
–> See
biotuner.metrics.compute_consonance()
to refer to consonance values to common intervals- When method = ‘euler’
Major (4:5:6) = 9
Minor (10:12:15) = 9
Major 7th (8:10:12:15) = 10
Minor 7th (10:12:15:18) = 11
Diminish (20:24:29) = 38
min_notes (int, default=3) – Minimal number of consonant frequencies in the chords.
Only relevant when method is set to ‘cons’.
n_harms (int, default=5) – Number of harmonics to compute for each frequency.
Only relevant when method is set to ‘subharm_tension’.
delta_lim (float, default=20) – Maximal distance between subharmonics of different frequencies to consider them as common subharmonics.
Only relevant when method is set to ‘subharm_tension’.
- Returns:
chords (List of lists (float)) – Axis 0 represents moments in time Axis 1 represents the sets of consonant frequencies
positions (List (int)) – positions on Axis 0
tr_harm (List (float)) – List of harmonicity value for each time point.
Examples
>>> 'USING RANDOM DATA' >>> # Set the number of time series and the number of samples per time series >>> n_time_series = 5 >>> n_samples = 1000 >>> >>> # Define the frequency range >>> min_freq = 1 >>> max_freq = 10 >>> precision = 0.1 >>> >>> # Generate the random time series >>> rand_integers = np.random.randint(min_freq * 10 / precision, max_freq * 10 / precision, size=(n_time_series, n_samples)) >>> time_series = rand_integers / 10 >>> >>> tc, _, _ = timepoint_consonance(time_series, method="cons", limit=0.2, min_notes=3, graph=False) >>> tc [[23.1, 84.7, 74.8, 81.6], [30.0, 75.0, 42.0], [10.0, 24.0, 32.5], [93.6, 83.2, 33.8], [67.6, 91.0, 18.2], [72.8, 11.7, 49.5, 89.1], [95.4, 53.0, 52.0, 64.0], [37.0, 44.4, 37.8, 69.3], [19.8, 50.4, 32.4], [21.5, 43.0, 17.2], [15.0, 54.0, 29.0, 92.8], [55.9, 30.1, 99.0, 40.5], [55.8, 21.7, 99.2], [30.5, 22.4, 12.6, 91.5]]
>>> 'USING THE BIOTUNER OBJECT' >>> # Load data >>> data = np.load('data_examples/EEG_pareidolia/parei_occi_L.npy') >>> # Keep a single time series. >>> data = data[0] >>> # Initialize biotuner object >>> bt = compute_biotuner(sf=1200, peaks_function='EMD') >>> # Extract spectral peaks >>> bt.peaks_extraction(data) >>> # Compute timepoint consonance using Spectral Centroid on IMFs. >>> bt.compute_spectromorph( method="SpectralCentroid", overlap=1, comp_chords=True, min_notes=4, cons_limit=0.2, cons_chord_method="cons", graph=False, ) >>> bt.spectro_chords [[15.47, 6.63, 31.68, 2.42], [5.72, 12.71, 26.64, 2.59], [15.31, 6.38, 2.53, 64.77], [67.59, 2.7, 33.79, 16.8]]
- compute_subharmonics(chord, n_harmonics, delta_lim)[source]#
Compute subharmonics of a chord and find the common subharmonics within a given delta limit.
- Parameters:
chord (list of int) – A list of integers representing the chord.
n_harmonics (int) – The number of harmonics to compute.
delta_lim (float) – The limit of delta between two subharmonics to be considered common. This value is in milliseconds (ms).
- Returns:
subharms (list of list of float) – A list of lists of subharmonics for each element in the chord.
common_subs (list of list of float) – A list of lists of common subharmonics within the delta limit.
delta_t (list of float) – A list of delta values for the common subharmonics.
Examples
>>> chord = [3, 5, 7] >>> subharms, common_subharms, delta_t = compute_subharmonics(chord, 5, 20) >>> print('subharms', subharms) >>> print('common_subharms', common_subharms) >>> print('delta_t', delta_t) subharms [[333.3333333333333, 666.6666666666666, 1000.0, 1333.3333333333333, 1666.6666666666667], [200.0, 400.0, 600.0, 800.0, 1000.0], [142.85714285714286, 285.7142857142857, 428.57142857142856, 571.4285714285714, 714.2857142857143]] common_subharms [[1000.0, 1000.0]] delta_t [0.0]
- compute_subharmonic_tension(chord, n_harmonics, delta_lim, min_notes=2)[source]#
Computes the subharmonic tension for a set of frequencies, based on the common subharmonics of a minimum of 2 or 3 frequencies. This metric has been adapted from Chan et al. (2019).
- Parameters:
chord (numpy array, shape (n,)) – Array containing the frequencies to compute subharmonic tension on.
n_harmonics (int) – Number of subharmonics to compute for each frequency.
delta_lim (float) – Maximal distance between subharmonics of different frequencies to consider them as common subharmonics.
min_notes (int, {2, 3}, default=2) – Minimal number of notes to consider common subharmonics.
- Returns:
common_subs (numpy array, shape (m,)) – Array containing the common subharmonics.
delta_t (numpy array, shape (m,)) – Array containing the subharmonic distances.
subharm_tension (float or str) – The subharmonic tension value, calculated as the average of the product of the subharmonic distance and the subharmonic frequency over all subharmonic pairs. Returns “NaN” if no valid subharmonic pairs are found.
harm_temp (numpy array, shape (m,)) – Array containing the subharmonic harmonic values.
Examples
>>> chord = [3, 5, 7] >>> _, _, subharm_tension, _ = compute_subharmonic_tension(chord, 5, 20, min_notes=2) >>> subharm_tension [0.0] >>> chord = [31, 51, 71] >>> _, _, subharm_tension, _ = compute_subharmonic_tension(chord, 5, 20, min_notes=2) >>> subharm_tension [0.23539483720429924]
Notes
The subharmonic tension is a measure of the perceived stability of a musical chord. The subharmonic tension is calculated as the average of the product of the subharmonic distance and the subharmonic frequency over all subharmonic pairs. A subharmonic is a frequency that is an integer divisor of another frequency. Common subharmonics are defined as subharmonics that are shared by at least min_notes notes in the chord.
References
Chan, P. Y., Dong, M., & Li, H. (2019). The science of harmony:A psychophysical basis for perceptual tensions and resolutions in music. Research, 2019.
- compute_subharmonics_2lists(list1, list2, n_harmonics, delta_lim, c=2.1)[source]#
Compute the subharmonic tension (Chan et al., 2019) for pairs of frequencies from two different lists, based on the common subharmonics of each pair.
- Parameters:
list1 (list of floats) – Values of the first set of frequencies to compute subharmonic tension on.
list2 (list of floats) – Values of the second set of frequencies to compute subharmonic tension on.
n_harmonics (int) – Number of subharmonics to compute for each frequency.
delta_lim (float) – Maximal distance between subharmonics of different frequencies to consider them as common subharmonics.
c (float, default=2.1) – Constant parameter for computing subharmonic tension.
- Returns:
tuple –
- common_subslist of lists (floats)
List of common subharmonics found for each pair of frequencies.
- delta_tlist of lists (floats)
List of the smallest differences between common subharmonics found for each pair of frequencies.
- sub_tension_finalfloat
The overall subharmonic tension value computed by averaging across all pairs of frequencies.
- harm_templist of floats
List of harmonic tensions for each subharmonic tension computed.
- pair_melodylist of floats
List containing the pair of frequency with the lowest subharmonic tension. Could be used in transitional harmony to derive subharmonic melodies.
Examples
>>> list1 = [5, 9] >>> list2 = [13, 20, 7] >>> n_harms = 5 >>> delta_lim = 30 >>> _, _, sub_tension, _, pair_melody = compute_subharmonics_2lists(list1, list2, n_harms, delta_lim, c=2.1) >>> subtension, pair_melody (0.05213398154647142,(5, 20))
- consonant_ratios(data, limit, sub=False, input_type='peaks', metric='cons', set_rebound=True)[source]#
Function that computes integer ratios from peaks with higher consonance
- Parameters:
data (List (float)) – Data can whether be frequency values or frequency ratios
limit (float) – minimum consonance value to keep associated pairs of peaks
sub (boolean, default=False) – When set to True, include ratios a/b when a < b.
input_type (str, default=’peaks’) – Choose between: - ‘peaks’ - ‘ratios’
metric (str, default=’cons’) – Choose between: - ‘cons’ - ‘harmsim’
set_rebound (bool, default=True) – Defines if the ratios are rebounded between 1 and 2. Only valid when input_type = ‘peaks’.
- Returns:
cons_ratios (List (float)) – list of consonant ratios
consonance (List (float)) – list of associated consonance values
Examples
>>> ratios = [1, 1.25, 1.34, 1.5, 1.67, 1.86] >>> cons_ratios, metrics = consonant_ratios(ratios, >>> 0.2, >>> sub=False, >>> input_type="ratios", >>> metric="cons") >>> cons_ratios, metrics (array([1. , 1.25, 1.5 ]), [2.0, 0.45, 0.8333333333333334])
>>> freqs = [3, 4.5, 11, 17] >>> ratios, metrics = consonant_ratios(freqs, >>> 0.2, >>> sub=False, >>> input_type="ratios", >>> metric="cons") >>> ratios, metrics (array([1.222, 1.5 , 1.833]), [0.20202020202020202, 0.8333333333333334, 0.25757575757575757])
- consonance_peaks(peaks, limit, limit_pairs=True)[source]#
This function computes consonance (for a given ratio a/b, when a < 2b), which is computed with the formula (a+b)/(a*b)) for each pair of peaks.
- Parameters:
peaks (list of floats) – Peaks represent local maximum in a spectrum.
limit (float) –
Minimum consonance value to keep associated pairs of peaks.
Comparisons with familiar ratios: Unison-frequency ratio 1:1 yields a value of 2
Octave-frequency ratio 2:1 yields a value of 1.5
Perfect 5th-frequency ratio 3:2 yields a value of 0.833
Perfect 4th-frequency ratio 4:3 yields a value of 0.583
Major 6th-frequency ratio 5:3 yields a value of 0.533
Major 3rd-frequency ratio 5:4 yields a value of 0.45
Minor 3rd-frequency ratio 5:6 yields a value of 0.366
Minor 6th-frequency ratio 5:8 yields a value of 0.325
Major 2nd-frequency ratio 8:9 yields a value of 0.236
Major 7th-frequency ratio 8:15 yields a value of 0.192
Minor 7th-frequency ratio 9:16 yields a value of 0.174
Minor 2nd-frequency ratio 15:16 yields a value of 0.129
- limit_pairsbool, default=True
Whether to compute consonance only for ratios where a > b. If False, also use ratios where a < b by dividing b iteratively.
- Returns:
consonance (list of floats) – Consonance scores for each pair of consonant peaks.
cons_pairs (list of lists of floats) – List of lists of each pair of consonant peaks.
cons_peaks (list of floats) – List of consonant peaks (no duplicates).
cons_tot (float) – Averaged consonance value for each pair of peaks.
Examples
>>> peaks = [3, 9, 11, 21] >>> consonance, cons_pairs, cons_peaks, cons_tot = consonance_peaks(peaks, limit=0.5, limit_pairs=True) >>> consonance, cons_pairs, cons_peaks, cons_tot ([1.3333333333333333, 1.1428571428571428], [[3, 9], [3, 21]], [9, 3, 21], 0.31024531024531027)
- spectral_flatness(harmonicity_values)[source]#
Calculate the spectral flatness of a power spectrum.
- Parameters:
harmonicity_values (ndarray) – Harmonicity values of the signal.
- Returns:
float – Spectral flatness of the signal.
- spectral_entropy(harmonicity_values)[source]#
Calculate the spectral entropy of a power spectrum.
- Parameters:
harmonicity_values (ndarray) – Harmonicity values of the signal.
- Returns:
float – Spectral entropy of the signal.
- spectral_spread(freqs, psd)[source]#
Calculate the spectral spread of a power spectrum.
- Parameters:
freqs (ndarray) – Frequencies for which the PSD is computed.
psd (ndarray) – Power spectral density of the signal.
- Returns:
float – Spectral spread of the signal.
- higuchi_fd(data, kmax)[source]#
Compute Higuchi Fractal Dimension of a power spectrum.
HFD is a technique used to determine the self-similarity of a signal. It has been widely used in analyzing time-series data, especially for detecting chaotic behavior in time-series data. Here we apply it the characterize the complexity of a power spectrum.
- Parameters:
data (ndarray) – The power spectrum data.
kmax (int) – The maximum delay; should be less than len(data)/3.
- Returns:
float – The Higuchi Fractal Dimension of the time series data.