Music Analysis Examples
This page contains code snippets demonstrating how to use Symusic for music analysis tasks.
Calculate Pitch Histogram
from symusic import Score
import numpy as np
import matplotlib.pyplot as plt
score = Score("path/to/file.mid")
pitches = []
for track in score.tracks:
# Optional: Filter for non-drum tracks
if not track.is_drum:
for note in track.notes:
pitches.append(note.pitch)
if pitches:
plt.figure()
plt.hist(pitches, bins=np.arange(129) - 0.5, density=True)
plt.title("Pitch Distribution")
plt.xlabel("MIDI Pitch")
plt.ylabel("Probability")
plt.xlim([-0.5, 127.5])
plt.show()
else:
print("No notes found.")
Calculate Note Density
from symusic import Score
score = Score("path/to/file.mid", ttype="second") # Load in seconds
duration = score.end()
num_notes = score.note_num()
if duration > 0:
note_density = num_notes / duration
print(f"Note Density: {note_density:.2f} notes per second")
else:
print("Score has zero duration or no notes.")
Get Average Tempo
from symusic import Score
score = Score("path/to/file.mid")
if score.tempos:
# Simple average (might not be musically accurate if tempos change significantly)
avg_tempo = sum(t.qpm for t in score.tempos) / len(score.tempos)
print(f"Average Tempo (unweighted): {avg_tempo:.1f} BPM")
# Time-weighted average (more accurate)
score_sec = score.to("second")
total_duration = score_sec.end()
weighted_tempo_sum = 0
last_time = 0
for i, tempo in enumerate(score_sec.tempos):
current_time = tempo.time
duration_at_prev_tempo = current_time - last_time
if i > 0:
weighted_tempo_sum += score_sec.tempos[i-1].qpm * duration_at_prev_tempo
last_time = current_time
# Add contribution of last tempo
if score_sec.tempos:
weighted_tempo_sum += score_sec.tempos[-1].qpm * (total_duration - last_time)
if total_duration > 0:
weighted_avg_tempo = weighted_tempo_sum / total_duration
print(f"Average Tempo (time-weighted): {weighted_avg_tempo:.1f} BPM")
else:
print("No tempo information found.")
(More analysis examples will be added here.)