---
title: "Relative Mode"
format: gfm
jupyter: python3
---
<!--conda activate relative_mode-->
<!--conda activate myenv--->

This package contains Python code for calculating _relative mode_ from an audio
signal. _Relative mode_ refers to the degree between how major or minor does
the segment of music sound at a given time. It is based on a classic
key-finding algorithm (Krumhansl-Schmuckler, 1990) and extracts the
pitch-class information using chromagrams. The relative mode is
calculated as the difference between the strongest major key and the
strongest minor key. Relative mode can vary from -1.0 (clearly in minor)
to + 1.0 (clearly in major) and gives a value between these extremes for the whole excerpt. Alternatively the algorithm can provide the output for each window of analysis (segments of 3 seconds as a default).

The algorithm and how it is evaluated is fully documented in a
manuscript titled “Major-minorness in Tonal music – Evaluation of
Relative Mode Estimation using Expert Ratings and Audio-Based
Key-finding Principles” by Tuomas Eerola and Michael Schutz (_Psychology of Music_, in press).
Key-finding Principles” by Tuomas Eerola and Michael Schutz (_Psychology of Music_, [2025](https://doi.org/10.1177/03057356251326065)).

### Libraries

```{python}
import librosa
import librosa.display
import matplotlib
import numpy as np
from matplotlib import pyplot as plt
import pandas as pd
```

### Load package using pip

```{python}
#| echo: false
#| eval: false
#pip install relative_mode
# local install
#pip install --no-index --find-links /srv/pkg ~/Desktop/relative_mode/dist/relative_mode-0.0.3.tar.gz
```

```{python}
#| echo: true
#| eval: false
pip install relative_mode
```

Make function calls explicit for the subsequent analyses. 

```{python}
#| echo: true
from src.relative_mode import Tonal_Fragment
from src.relative_mode import relative_mode
from src.relative_mode import RME_across_time
```

### Load a music example

Recording of J.S. Bach's _C Major Prelude_ (WTC Book I) (an extract).

```{python}
#| label: fig-waveform
#| fig-cap: "Waveform of the C Major Prelude."
filename = 'data/Bach_1_Gould_0_Major_bachGould1971.wav'
y, sr = librosa.load(filename)
plt.figure(figsize=(9,2.5))
librosa.display.waveshow(y, sr = sr)
plt.show()
```

### Estimate relative mode

Here we don't specify any parameters but just run `relative_mode` using the default parameters.

```{python}
RM, RM_segments = relative_mode(y = y, sr = sr)
print(round(RM['tondeltamax'][0],3))
```

The value of `0.258` could be called "moderately in major". Value closer to 0 would indicate no clear tendency for major or minor and any value below -0.30 would suggest clearly in minor key.

The relative mode can be computed with a different options. You can alter key profile (e.g. `krumhansl`, `albrecht` (default), `aarden`, or `bellman`), similarity metrics (`pearson`, `cosine` (default), or `euclidean`), chromatype from `CENS` to `CQT`. There are also some alternative outputs of the measure.


Here's a variant analysis using a different distance measure and chroma type:

```{python}
RM2, RM2_segments = relative_mode(y = y, sr = sr, profile = 'simple', distance = 'pearson', chromatype = 'CQT')
print(RM2)
```

This outputs the `tondeltamax` value of `0.145`, which is the relative mode with these parameters. The extra outputs refer to the highest correlation coefficient with the major (`tonmaxmaj`) and minor (`tonmaxmin`). Note that the distance metrics have different scales so the outputs have been rescaled to be more easily comparable.

### Estimate relative mode across the excerpt

The second output provides a relative mode value for each window of the analysis. The segment timing reflects the `hoplen` argument. Here we also remove the percussive sounds with an extra parameter (`remove_percussive=True`):

```{python}
RM, RM_segments = relative_mode(y = y, sr = sr, winlen = 3.5, hoplen = 1.5, remove_percussive=True)
print(RM_segments)
```

One can also visualise the relative mode across time. In this case there is a cubic interpolation to make the lines between the windows appear smooth, but one can alter this interpolation parameter.

```{python}
#| label: fig-continuous
#| fig-cap: "Relative mode across time."
fig, RM3 = RME_across_time(filename = filename, winlen = 2, hoplen = 2, cropfirst = 0, croplast = 15, chromatype = 'CENS', profile = 'albrecht', distance = 'cosine', plot = True, interpolation='cubic')
fig
plt.show()
```

# Extras

## Weights to normalise the output across distance metrics

The `tondeltamax` output depends on the distance metric used. To normalise close to between -1 and +1 for an easier use of the algorithm, a weight is assigned to the raw delta value. These weights were empirically derived by creating all possible 3 to 5-note chords and calculating the relative mode with the available distance metrics. For cosine distance metric, the weight is `6.5`, for pearson correlation, `10.0`, and for euclidean distance, `3.0`. The purpose is to keep the output more easily understandable `(max major corr. - max minor corr.) * weigth`.

## Alternative analyses

In the article (Eerola & Schutz, [2025](https://doi.org/10.1177/03057356251326065)), we assess various parameters of the model (key profiles, distance measures, alternative formulations of the model) in Experiment 1. We also examine what could explain the variations in model success across recordings used in Experiment 3. Here we briefly report these alternative explorations. 

### Experiment 1: Alternative analyses

The model compares the difference between highest maximum major key strength and the maximum minor key strength. We also have two alternative formulations of the model, one that utilises comparison with the parallel minor and another one relying on the relative minor.

The parallel minor key of the major key received lower correlation with the expert ratings (_r_ = 0.698) than the actual model (_r_ = 0.840). The second alternative relies on the relative minor key of the major key. This alternative received a lower correlation (_r_ = 0.766) with the expert ratings compared to the proposed model. For this reason, we did not pursue these two alternatives further. 

We also run alternative formulations of window length (1 to 5 seconds) and overlap (0 to 75% overlap) which did not provide substantially better fit with the data. Finally, the way of summarizing the RME across the analysis windows with the mean values did not appear to be significantly different from the taking median of the predictions within the analysis windows (_r_ = 0.785).

### Experiment 3: Alternative analyses

To identify the consistent noise factors in the RME analysis from audio, we extracted dynamics, several timbral descriptors (brightness, spectral centroid, spectral flux, rms, roughness) and tempo descriptors for each excerpt using [Essentia](https://essentia.upf.edu), and added these as additional predictors to the regression with RME model predicting the expert ratings. However, no single audio descriptor could contribute significantly (more than 2 % of the variance accounted) to the model that already had a highly successful predictor (RME) within it. A more extensive analysis of the potential additional considerations would benefit from a larger set of materials and from systematic alterations of the most plausible variations of these factors. 

### Improvements to the implementation

`Version 0.0.4`, 7 February 2026

- `RME_across_time` accepts interpolation parameter to control the way output is interpolated across the analysis windows. `cubic` is the default, but `linear` and `none` are possible as well.

- The output of the segments has now explicit time code (onset time in seconds).

- The parameters `cropfirst` and `cropfirst` now work for `RME_across_time`.

- The output of the `RM_across_time` has now `tonmaxmaj` and `tonmaxmin` output and the numeric output is unaffected by interpolation.

- A new option `remove_percussive` has been added to remove percussive noise (using `Librosa`'s median filtering solution, see `librosa.decompose.hpss`) from the signal. Filtering is set to `False` by default.  

# References

Eerola, T. & Schutz, M. (2025). Major-minorness in Tonal music – Evaluation of Relative Mode Estimation using Expert Ratings and Audio-Based Key-finding Principles. _Psychology of Music, 0(0)_. [https://doi.org/10.1177/03057356251326065](https://doi.org/10.1177/03057356251326065)

