#!/usr/bin/env python3
import json, sys
try:
    import librosa
    import numpy as np
except Exception as e:
    print(json.dumps({"error": f"librosa missing: {e}"})); sys.exit(0)
path=sys.argv[1]
y,sr=librosa.load(path,sr=22050,mono=True)
tempo,_=librosa.beat.beat_track(y=y,sr=sr)
bpm=float(np.asarray(tempo).reshape(-1)[0]) if np.asarray(tempo).size else None
chroma=librosa.feature.chroma_cqt(y=y,sr=sr)
profile=np.mean(chroma,axis=1)
major=np.array([6.35,2.23,3.48,2.33,4.38,4.09,2.52,5.19,2.39,3.66,2.29,2.88])
minor=np.array([6.33,2.68,3.52,5.38,2.60,3.53,2.54,4.75,3.98,2.69,3.34,3.17])
notes=['C','C#','D','D#','E','F','F#','G','G#','A','A#','B']
best=(-999,None,None)
for root in range(12):
    for mode,p in [('major',major),('minor',minor)]:
        score=float(np.corrcoef(profile,np.roll(p,root))[0,1])
        if score>best[0]:best=(score,root,mode)
camelot_major=['8B','3B','10B','5B','12B','7B','2B','9B','4B','11B','6B','1B']
camelot_minor=['5A','12A','7A','2A','9A','4A','11A','6A','1A','8A','3A','10A']
root,mode=best[1],best[2]
print(json.dumps({'bpm':round(bpm,2) if bpm else None,'key':f'{notes[root]} {mode}','camelot':(camelot_major if mode=='major' else camelot_minor)[root],'duration':round(float(librosa.get_duration(y=y,sr=sr)),3)}))
