feat: fix sample variety per section and reorganize sample library
- Fix compose.py to select different samples per section instead of one per role
- Add select_many() to SampleSelector for diverse sample selection
- Migrate 862 samples from scattered dirs to libreria/samples/{role}/
- Rename files with consistent convention: {role}_{key}_{bpm}_{character}_{hash}.wav
- Add migrate_library.py script with dry-run and verification
- Backup original index as sample_index_pre_migration.json
- 72 tests passing
This commit is contained in:
@@ -235,13 +235,11 @@ def build_section_tracks(
|
||||
# Build one track per role
|
||||
tracks: list[TrackDef] = []
|
||||
|
||||
# Track used sample IDs per role for diversity
|
||||
used_sample_ids: dict[str, list[str]] = {}
|
||||
|
||||
for role, role_cfg in roles.items():
|
||||
sample_role = ROLE_TO_SAMPLE_ROLE.get(role, role)
|
||||
generator_name = role_cfg.get("notes_template", "")
|
||||
|
||||
# Select sample for this role
|
||||
sample_match = selector.select_one(role=sample_role, key=key, bpm=bpm)
|
||||
sample_path = sample_match.get("original_path") if sample_match else None
|
||||
|
||||
# Collect clips for each section
|
||||
section_clips: list[ClipDef] = []
|
||||
@@ -251,6 +249,20 @@ def build_section_tracks(
|
||||
vel_mult = section.energy
|
||||
vol_mult = section.energy
|
||||
|
||||
# For audio roles, select a different sample per section
|
||||
sample_path = None
|
||||
if role in AUDIO_ROLES:
|
||||
exclude = used_sample_ids.get(role, [])
|
||||
diverse_results = selector.select_diverse(
|
||||
role=sample_role, n=1, exclude=exclude, key=key, bpm=bpm
|
||||
)
|
||||
if diverse_results:
|
||||
sample = diverse_results[0]
|
||||
sample_path = sample.get("original_path")
|
||||
sample_id = sample.get("file_hash", "")
|
||||
if sample_id:
|
||||
used_sample_ids.setdefault(role, []).append(sample_id)
|
||||
|
||||
if role in ROLE_RHYTHM_GENERATORS:
|
||||
gen_name = ROLE_RHYTHM_GENERATORS[role]
|
||||
note_dict = get_notes(gen_name, section.bars, velocity_mult=vel_mult)
|
||||
@@ -281,12 +293,12 @@ def build_section_tracks(
|
||||
gen_fn = ROLE_MELODIC_GENERATORS[role]
|
||||
note_list = gen_fn(key=key, bars=section.bars, velocity_mult=vel_mult)
|
||||
midi_notes = melodic_to_midi(note_list)
|
||||
# Melodic roles use MIDI instruments — no audio_path needed
|
||||
clip = ClipDef(
|
||||
position=sec_offset * 4.0,
|
||||
length=section.bars * 4.0,
|
||||
name=f"{section.name.capitalize()} {role.capitalize()}",
|
||||
midi_notes=midi_notes,
|
||||
audio_path=sample_path,
|
||||
)
|
||||
section_clips.append(clip)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user