"""Fine sample-descriptor ontology for zero-shot audio classification.

Each entry is a natural-language descriptor a contrastive audio model (CLAP) can
match an unknown one-shot against. Many sharp anchors separate better than 12 coarse
family prompts — especially the melodic cluster (keys/lead/synth/pad) and the
bass↔kick boundary. At classify time we score every descriptor, then MARGINALIZE
(sum probabilities) over the descriptors of each FAMILY → the 12-way fleet target.

This is the 'vocabulary the classifier listens with'. Extend freely — more, more
specific terms generally help. `FAMILY_OF[descriptor] = family` is the only contract.
A second, finer label per descriptor (`SUBLABEL`) is kept for future fine-grained
output (e.g. '808 kick' vs 'acoustic kick') and for PANNs/AudioSet mapping work."""

# family → list of (descriptor phrase, optional sub-label). Sub-label defaults to the
# phrase. Phrases are written to drop cleanly into "this is the sound of {phrase}".
ONTOLOGY = {
    "kick": [
        "a kick drum", "an 808 kick drum", "a punchy acoustic bass drum",
        "a boomy four-on-the-floor kick", "a distorted hardcore kick",
        "a tight techno kick", "a deep sub kick with a click",
    ],
    "snare": [
        "a snare drum", "an acoustic snare backbeat", "a tight electronic snare",
        "a 909 snare", "a snappy drum-machine snare", "a rimshot",
        "a single hand clap", "a layered clap stack", "a side-stick",
    ],
    "hat": [
        "a closed hi-hat tick", "an open hi-hat", "a hi-hat groove",
        "a ride cymbal", "a crash cymbal", "a metallic cymbal sizzle",
        "a short bright shaker tick",
    ],
    "perc": [
        "a conga hit", "a bongo drum", "a tom-tom", "a tabla", "a djembe",
        "a tambourine", "a woodblock", "a cowbell", "a clave", "a guiro scrape",
        "a tuned hand-percussion one-shot",
    ],
    "break": [
        "a drum break loop", "an amen breakbeat", "a chopped jungle break",
        "a funky drummer loop", "a full drum loop with kick snare and hi-hats",
        "a breakbeat rhythm with swing",
    ],
    "bass": [
        "a sustained sub bass note", "a deep low bass tone", "a reese bass",
        "an acid 303 bassline", "a fingered bass guitar", "a wobble dubstep bass",
        "a round synth bassline", "a low droning bass", "a plucked bass note",
    ],
    "keys": [
        "a grand piano chord", "an electric piano", "a rhodes chord",
        "a wurlitzer keyboard", "a hammond organ", "a clean electric guitar chord",
        "an acoustic guitar pluck", "a harpsichord", "a clavinet", "a marimba",
    ],
    "lead": [
        "a bright synth lead melody", "a fast synth arpeggio", "a plucky lead synth",
        "a chiptune square-wave lead", "a sawtooth lead line", "a brass stab",
        "a whistle-like lead melody",
    ],
    "synth": [
        "a polysynth chord stab", "an electronic synthesizer tone", "an FM synth bell",
        "a detuned supersaw chord", "a retro chiptune synth", "a digital synth pad stab",
        "a glassy synth texture",
    ],
    "pad": [
        "a warm synth pad", "a slow ambient drone", "an evolving sustained texture",
        "a string ensemble pad", "a breathy choir pad", "an atmospheric wash",
        "a cinematic drone bed",
    ],
    "fx": [
        "a riser sweep", "a downlifter", "a white-noise sweep", "an impact boom",
        "a reverse cymbal swell", "a vinyl crackle texture", "a glitch effect",
        "a sci-fi whoosh", "a foley sound effect", "a tape stop",
    ],
    "vox": [
        "a sung vocal phrase", "a spoken-word sample", "a chopped vocal", "a rap acapella",
        "a layered choir", "a vocal scat", "a movie dialogue clip", "a crowd chant",
        "a breathy vocal ad-lib",
    ],
}

# flattened parallel arrays + reverse map (the classify-time contract)
PROMPTS, FAMILY_OF = [], []
for _fam, _terms in ONTOLOGY.items():
    for _t in _terms:
        PROMPTS.append("this is the sound of " + _t)
        FAMILY_OF.append(_fam)

N_TERMS = len(PROMPTS)
FAMILIES = list(ONTOLOGY)
