59 lines
2.0 KiB
Python
59 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
import typing
|
|
|
|
import generator.score
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class ArrangementSection:
|
|
label: str
|
|
source_measure_index: int
|
|
measure_count: int
|
|
section_index: int
|
|
role: typing.Literal["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) -> typing.Literal["accompaniment", "melody", "vocal", "rest", "slash"]:
|
|
if part_type == "acoustic":
|
|
return "slash" if section_index == 3 else "accompaniment"
|
|
if part_type == "electric":
|
|
if section_index == 4:
|
|
return "slash"
|
|
if section_index == 2:
|
|
return "melody"
|
|
if section_index in {1, 3, 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 = generator.score.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),
|
|
("Acoustic Solo", body_start, body_measure_count, 3),
|
|
("Electric 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
|
|
]
|