Introduction

TOVIS turns musical audio or note annotations into chroma features, compares those features with scale templates, and visualizes tonal and formal structure.

A runnable example

Install TOVIS as described in Installation, then run the following code in Python. It synthesizes a three-second C-major chord, extracts an STFT chromagram, computes scale likelihoods, and saves tovis-introduction.png in the current directory. No datasets, audio downloads, or model checkpoints are needed. Saving the plot also works without a graphical desktop.

import matplotlib.pyplot as plt
import numpy as np

import tovis
from tovis.visualization import plot_chromagram, plot_scale_likelihood

sample_rate = 22050
time = np.arange(3 * sample_rate) / sample_rate
frequencies = [261.63, 329.63, 392.00]  # C4, E4, G4
audio = sum(np.sin(2 * np.pi * f * time) for f in frequencies) / 3

chroma, feature_rate = tovis.compute_chromagram(
    audio, sample_rate=sample_rate, backend="STFT"
)
likelihood = tovis.scale_analysis_templates(chroma, template_version="binary")

fig, axes = plt.subplots(2, 1, figsize=(10, 6))
plot_chromagram(chroma, feature_rate=feature_rate, ax=axes[0])
plot_scale_likelihood(likelihood, feature_rate=feature_rate, ax=axes[1])
fig.tight_layout()
fig.savefig("tovis-introduction.png", dpi=150)
plt.close(fig)

Reading the results

chroma has shape (12, n_frames). Its rows represent pitch classes ordered C, C-sharp, D, …, B; columns represent successive audio frames. feature_rate is measured in frames per second, so frame n corresponds to time n / feature_rate. A C-major chord emphasizes C, E, and G.

likelihood compares each chroma frame with twelve transposed major-scale templates. The default scale labels describe each scale’s position on the circle of fifths relative to C. These values describe template agreement; they are not calibrated probabilities or a definitive key estimate.

Use your own audio

Replace the synthesis and chromagram extraction in the example with:

chroma, feature_rate = tovis.compute_chromagram_from_file("your-audio.wav")

The default backend is CQT. STFT, CQT, VQT, and IIR are available without neural models. See Installation for the additional requirements of the neural backends.

Use note annotations

For symbolic input, provide note start and end times in seconds and MIDI pitch numbers in a DataFrame:

import pandas as pd

notes = pd.DataFrame({
    "start": [0.0, 0.0, 0.0],
    "end": [3.0, 3.0, 3.0],
    "pitch": [60, 64, 67],
})
chroma, feature_rate = tovis.compute_chromagram_from_annotations(
    notes, feature_rate=10.0
)

This returns a (12, 30) matrix at ten frames per second. It can be used with the same scale-analysis and visualization functions. See API Reference for smoothing, normalization, synchronization, and structure-analysis options.