Skip to content

Add one-shot vs loop sample classification#3

Merged
LukeMainwaring merged 2 commits into
mainfrom
oneshot-vs-loop
Mar 20, 2026
Merged

Add one-shot vs loop sample classification#3
LukeMainwaring merged 2 commits into
mainfrom
oneshot-vs-loop

Conversation

@LukeMainwaring

Copy link
Copy Markdown
Owner

Summary

  • Add is_loop boolean field to distinguish one-shot samples (single kicks, snares, chord stabs) from loops (drum patterns, basslines, melodic phrases) — any sample type can be either
  • Tiered inference during seeding: filepath keyword matching (word-boundary regex) first, then librosa audio heuristics (duration, onset count, onset regularity) as fallback
  • Skip key/BPM computation for one-shots (meaningless for single hits), propagate awareness through agent tools, system prompt, and frontend

Changes

  • services/audio_analysis.py: New analyze_and_classify() function that infers loop/one-shot and extracts metadata in a single audio load pass
  • models/sample.py: Added is_loop column with server_default, added is_loop filter to search_by_clap()
  • schemas/sample.py: is_loop on SampleSchema and SampleSearchRequest
  • agents/sample_agent.py: System prompt section on one-shot vs loop behavior rules
  • agents/tools/: All three tool files conditionally show key/BPM only for loops; suggest_complement() skips key compatibility for one-shot sources
  • routers/samples.py: Pass is_loop filter through search endpoint
  • scripts/: All scripts converted to async (use get_async_sqlalchemy_session), shared find_audio_file helper extracted to __init__.py
  • core/config.py: Fixed env_file path (was resolving to backend/.env instead of project root), added extra="ignore" for non-Settings env vars
  • pyproject.toml: Added sqlalchemy[asyncio] extra (provides greenlet)
  • Frontend: One-shot/loop badge on sample cards, segmented filter toggle (All/One-shots/Loops) above type filters
  • Migration: c1e3a6c19709_add_is_loop_column

Test Plan

  • Run uv run seed-db — verify one-shots get key=None, bpm=None; loops get full metadata
  • Verify filepath keyword inference (samples in "one-shot" dirs → is_loop=False, "loop" dirs → is_loop=True)
  • Hit GET /api/samples — verify is_loop appears in response
  • Ask agent to analyze a one-shot — should show "Category: one-shot" with no key/BPM
  • Ask agent to analyze a loop — should show "Category: loop" with key/BPM
  • Test frontend one-shot/loop filter toggle and badge display
  • Run uv run pre-commit run --all-files and cd frontend && pnpm lint

🤖 Generated with Claude Code

@LukeMainwaring LukeMainwaring merged commit 0146e60 into main Mar 20, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant