Files
product-vamp/generator/arrange/form.py
T
khodowany fe42d811fa
ci / checks (push) Successful in 42m54s
Formatting
2026-09-15 00:06:02 -05:00

59 lines
2.1 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
from generator.score import body_start_measure_index
@dataclass(frozen=True)
class ArrangementSection:
label: str
source_measure_index: int
measure_count: int
section_index: int
role: Literal["rhythm", "accompaniment", "melody", "vocal", "rest", "slash"]
def phrase_aware_edge_measure_count(body_measure_count: int) -> int:
if body_measure_count >= 8:
return 8
if body_measure_count >= 4:
return 4
return body_measure_count
def section_role(part_type: str, section_index: int) -> Literal["rhythm", "accompaniment", "melody", "vocal", "rest", "slash"]:
if part_type == "acoustic":
return "slash" if section_index == 3 else "rhythm"
if part_type == "electric":
if section_index == 4:
return "slash"
if section_index == 2:
return "melody"
if section_index in {1, 5, 6}:
return "accompaniment"
return "rest"
return "vocal" if section_index in {1, 5, 6} else "rest"
def full_arrangement_sections(measures: list[dict], part_type: str) -> list[ArrangementSection]:
if not measures:
return []
body_start = body_start_measure_index(measures)
if body_start >= len(measures):
return []
body_measure_count = len(measures) - body_start
edge_measure_count = phrase_aware_edge_measure_count(body_measure_count)
edge_source_measure = body_start + body_measure_count - edge_measure_count
specs = (
("Rhythm Lead-in", edge_source_measure, edge_measure_count, 0),
("Vocal Melody", body_start, body_measure_count, 1),
("Guitar Melody", body_start, body_measure_count, 2),
("Guitar Solo", body_start, body_measure_count, 3),
("Guitar Solo", body_start, body_measure_count, 4),
("Vocal Melody", body_start, body_measure_count, 5),
("Ending", edge_source_measure, edge_measure_count, 6),
)
return [
ArrangementSection(label=label, source_measure_index=start, measure_count=count, section_index=index, role=section_role(part_type, index))
for label, start, count, index in specs
if count > 0
]