feat(midi): extract lyric meta-events and vocal melody into sidecar payloads#1038
feat(midi): extract lyric meta-events and vocal melody into sidecar payloads#1038ChrisBeWithYou wants to merge 1 commit into
Conversation
…ayloads MIDI import previously ignored lyric meta-events entirely, so karaoke MIDI files lost their lyrics and vocal melody on import. - new extract_midi_lyrics(midi_path, audio_offset): returns spec 7.1 lyrics + spec 7.2 vocal_pitch payloads, or None when the file has no usable lyrics (existing behavior unchanged) - collects 0x05 Lyric events, with 0x01 Text as a conservative fallback on vocal-ish / Words / Karaoke tracks only (avoids importing copyright notices as lyrics) - .kar conventions handled: '/' and '\' line-break prefixes fold onto the previous syllable as 7.1 '+'; '@'/'%' metadata dropped - per-stream word conventions: hyphen-delimited streams pass '-' joins through; space-delimited streams synthesize joins; whole-word streams get none; line ends become trailing '+' (stripping a '-' first) - melody pairing: greedy time-ordered, one note per syllable within 0.30s; paired syllables snap t/d to the note so both sidecars stay mirrored per 7.2; unpaired syllables remain lyrics-only (spec-legal) - vocal-track selection mirrors the GP importer's idiom (name keywords + GM programs 52-54/85-87); SMF type 0 isolates vocal-program channels, type 1/2 trusts the lyric-carrying note track - unpaired lyric durations run to the next syllable, clamped 0.1-2.0s Callers (the editor plugin's import flow) wire the payloads into the pak in a follow-up; no manifest keys are written here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: ChrisBeWithYou <chris@rifflarr.local>
|
Warning Review limit reached
Next review available in: 59 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What
lib/midi_import.pydrops lyric meta-events entirely, so karaoke MIDI files lose both lyrics and vocal melody on import. This adds a third extraction flow (alongside keys and drums):extract_midi_lyrics(midi_path, audio_offset=0.0)returns{"lyrics": [...§7.1...], "lyrics_source": "authored", "vocal_pitch": {...§7.2...} | None}, orNonewhen the file has no usable lyrics (current behavior unchanged). Payloads only — the pak/manifest is assembled by the editor plugin, which gets a small follow-up PR to consume this (tracked on the org board)./and\line-break prefixes fold onto the previous syllable as §7.1+;@/%metadata dropped.-joins through untouched; space-delimited streams synthesize-joins; whole-word streams get none; line ends become trailing+(a-is stripped first — joins can't cross a line break).t/dto the note so the two sidecars stay mirrored per §7.2; melisma extras skipped; unpaired syllables stay lyrics-only (spec-legal). Vocal-track selection mirrors the GP importer's idiom (name keywords + GM programs 52-54/85-87); SMF type-0 isolates vocal-program channels, type-1/2 trusts the lyric-carrying note track._build_tick_to_seconds(correct type-0/1/2 scoping).Tests
New
tests/test_midi_lyrics.py(15 tests, in-memory mido fixtures matching the existing midi test style): both-sidecars from a vocal track; GM-program detection without a name; lyrics-only; no-lyrics →None; unpaired durations;.kar/and\→+; hyphen pass-through; join synthesis; embedded newlines; Text fallback with@KMIDIdropped; Text rejected on non-vocal tracks; format-0 channel isolation; format-0 lyrics-only fallback;audio_offseton both payloads.test_midi_lyrics.py: 15 passed.test_midi_import.py+test_midi_import_drums.py+test_midi_tempo_map.py: 44 passed.Notes for review
lyrics_source: "authored"— lyric meta events are chart-author data, not transcription; nolyric_transcription/pitch_extractionprovenance blocks are written (reserved for automated engines).🤖 Generated with Claude Code