feat: SDD workflow — test sync, song generation + validation, ReaScript hybrid pipeline
- compose-test-sync: fix 3 failing tests (NOTE_TO_MIDI, DrumLoopAnalyzer mock, section name) - generate-song: CLI wrapper + RPP validator (6 structural checks) + 4 e2e tests - reascript-hybrid: ReaScriptGenerator + command protocol + CLI + 16 unit tests - 110/110 tests passing - Full SDD cycle (propose→spec→design→tasks→apply→verify) for all 3 changes
This commit is contained in:
63
scripts/generate.py
Normal file
63
scripts/generate.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""REAPER .rpp song generator — thin CLI wrapper around compose.main().
|
||||
|
||||
Usage:
|
||||
python scripts/generate.py --bpm 95 --key Am --output output/song.rpp --seed 42
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
_ROOT = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(_ROOT))
|
||||
import compose
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="Generate a REAPER .rpp reggaeton song.")
|
||||
parser.add_argument("--bpm", type=float, default=95, help="BPM (default: 95)")
|
||||
parser.add_argument("--key", default="Am", help="Musical key (default: Am)")
|
||||
parser.add_argument(
|
||||
"--output", default="output/song.rpp", help="Output .rpp path (default: output/song.rpp)"
|
||||
)
|
||||
parser.add_argument("--seed", type=int, default=42, help="Random seed (default: 42)")
|
||||
parser.add_argument(
|
||||
"--validate", action="store_true", help="Run validator after generation"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# BPM validation
|
||||
if args.bpm <= 0:
|
||||
raise ValueError("bpm must be > 0")
|
||||
|
||||
# Ensure output directory exists
|
||||
output_path = Path(args.output)
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Delegate to compose.main() — set sys.argv so compose's argparse works
|
||||
sys.argv = [
|
||||
sys.argv[0],
|
||||
"--bpm", str(args.bpm),
|
||||
"--key", args.key,
|
||||
"--output", str(output_path),
|
||||
"--seed", str(args.seed),
|
||||
]
|
||||
compose.main()
|
||||
|
||||
# Post-generation validation
|
||||
if args.validate:
|
||||
from src.validator.rpp_validator import validate_rpp_output
|
||||
|
||||
errors = validate_rpp_output(str(output_path), expected_bpm=args.bpm, expected_bars=52)
|
||||
if errors:
|
||||
print("Validation errors:", file=sys.stderr)
|
||||
for err in errors:
|
||||
print(f" - {err}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
print("Validation passed.", file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user