Add LRCLIB freestyle notes and linebreak support - #57
Conversation
Parse parenthesized text (backing vocals) and brackets [ad-libs] from LRCLIB lyrics as freestyle notes (F prefix in UltraStar). Use LRCLIB line breaks for UltraStar linebreak placement instead of silence-based detection when available. - TranscribedData: add is_freestyle, line_break_after fields - MidiSegment: add note_type (:/F), line_break_after fields - lyrics_corrector: parse (brackets) as freestyle, track line breaks - midi_creator: transfer freestyle/linebreak from TranscribedData - ultrastar_writer: use note_type, prefer LRCLIB linebreaks - Propagate flags through merge, split, absorb post-processing - 40 tests covering tokenizer, parser, and end-to-end correction Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThis change adds LRCLIB metadata propagation throughout the audio processing pipeline. New Changes
Sequence Diagram(s)sequenceDiagram
participant LyricsParser as Lyrics Parser
participant RefWords as Reference Words
participant WhisperWords as Whisper Words (TranscribedData)
participant MidiCreator as MIDI Creator
participant MidiSegments as MIDI Segments
participant MergeLogic as Merge/Split Logic
participant UltrastarWriter as Ultrastar Writer
LyricsParser->>RefWords: Parse lyrics with freestyle<br/>& linebreak metadata
RefWords->>LyricsParser: [is_freestyle, line_break_after]
WhisperWords->>MidiCreator: Transcribed words (plain)
MidiCreator->>MidiCreator: Match & apply ref metadata
MidiCreator->>MidiSegments: Copy is_freestyle<br/>& line_break_after
MidiSegments->>MergeLogic: Segments with metadata
MergeLogic->>MergeLogic: Merge/split preserves<br/>metadata flags
MergeLogic->>MidiSegments: Updated segments
MidiSegments->>UltrastarWriter: Final MIDI segments
UltrastarWriter->>UltrastarWriter: Emit note_type (F/normal)<br/>& linebreaks per metadata
UltrastarWriter->>UltrastarWriter: Generate Ultrastar output
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
pytest/modules/Speech_Recognition/test_lyrics_corrector.py (1)
335-340: Rename unused variable to silence linter warning.The
resultvariable is unpacked but never used. Prefix with underscore per Python convention.♻️ Proposed fix
- data, result = correct_transcription_from_lyrics( + data, _ = correct_transcription_from_lyrics( td, "Hello (ooh)\nworld" )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pytest/modules/Speech_Recognition/test_lyrics_corrector.py` around lines 335 - 340, The test unpacks two values from correct_transcription_from_lyrics into variables data and result but never uses result; rename it to _result to follow Python linter convention for unused variables. Locate the call to correct_transcription_from_lyrics in test_lyrics_corrector.py (the line using data, result = correct_transcription_from_lyrics(...)) and change the second identifier to _result so the linter no longer flags an unused variable.src/modules/Midi/midi_creator.py (1)
217-225: Consider adding a warning when list lengths mismatch.The guard
i < len(midi_segments)prevents index errors, but if lengths differ, metadata from trailingtranscribed_dataentries is silently dropped. While this shouldn't occur in normal operation (both lists derive from the same input), a warning would help diagnose edge-case bugs.♻️ Optional: Add a debug warning for length mismatch
# Transfer LRCLIB metadata (freestyle, linebreak) from TranscribedData + if len(transcribed_data) != len(midi_segments): + print(f"{ULTRASINGER_HEAD} Warning: TranscribedData ({len(transcribed_data)}) " + f"and MidiSegments ({len(midi_segments)}) length mismatch during metadata transfer") for i, td in enumerate(transcribed_data): if i < len(midi_segments):🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/modules/Midi/midi_creator.py` around lines 217 - 225, The loop that transfers LRCLIB metadata from transcribed_data to midi_segments silently drops trailing transcribed_data when len(transcribed_data) > len(midi_segments); add a warning when the lengths mismatch so this situation is visible. Before or after the for-loop that iterates over transcribed_data (the block referencing midi_segments and td.is_freestyle/td.line_break_after), check if len(transcribed_data) != len(midi_segments) and emit a warning via the module logger (e.g., logger.warning or logging.warning) including both lengths and contextual info; keep the existing i < len(midi_segments) guard so behavior is unchanged but now logged for debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/modules/Ultrastar/ultrastar_writer.py`:
- Around line 164-166: The condition in the if statement uses mixed and/or
without parentheses so the any(...) branch can fire even for the final segment;
change the boolean grouping so the "not final segment" guard applies to both
checks. Specifically, in the if that references silence_split_duration, i,
len(midi_segments), silence, and separated_word_silence, rewrite the boolean to:
silence_split_duration is not None and i != len(midi_segments) - 1 and (silence
> silence_split_duration or any(s > silence_split_duration for s in
separated_word_silence)) so the final-segment guard is evaluated before the or.
---
Nitpick comments:
In `@pytest/modules/Speech_Recognition/test_lyrics_corrector.py`:
- Around line 335-340: The test unpacks two values from
correct_transcription_from_lyrics into variables data and result but never uses
result; rename it to _result to follow Python linter convention for unused
variables. Locate the call to correct_transcription_from_lyrics in
test_lyrics_corrector.py (the line using data, result =
correct_transcription_from_lyrics(...)) and change the second identifier to
_result so the linter no longer flags an unused variable.
In `@src/modules/Midi/midi_creator.py`:
- Around line 217-225: The loop that transfers LRCLIB metadata from
transcribed_data to midi_segments silently drops trailing transcribed_data when
len(transcribed_data) > len(midi_segments); add a warning when the lengths
mismatch so this situation is visible. Before or after the for-loop that
iterates over transcribed_data (the block referencing midi_segments and
td.is_freestyle/td.line_break_after), check if len(transcribed_data) !=
len(midi_segments) and emit a warning via the module logger (e.g.,
logger.warning or logging.warning) including both lengths and contextual info;
keep the existing i < len(midi_segments) guard so behavior is unchanged but now
logged for debugging.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 57c5c8f4-337c-40f0-8d4d-f1f87305f91a
📒 Files selected for processing (8)
pytest/modules/Speech_Recognition/test_lyrics_corrector.pysrc/UltraSinger.pysrc/modules/Midi/MidiSegment.pysrc/modules/Midi/midi_creator.pysrc/modules/Pitcher/pitch_change_splitter.pysrc/modules/Speech_Recognition/TranscribedData.pysrc/modules/Speech_Recognition/lyrics_corrector.pysrc/modules/Ultrastar/ultrastar_writer.py
- Fix operator precedence bug in silence-based linebreak condition (any() could trigger on final segment due to missing parentheses) - Rename unused `result` variable to `_` in test - Add warning when TranscribedData/MidiSegments length mismatch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
- Fix operator precedence bug in silence-based linebreak condition (any() could trigger on final segment due to missing parentheses) - Rename unused `result` variable to `_` in test - Add warning when TranscribedData/MidiSegments length mismatch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add LRCLIB freestyle notes and linebreak support
Summary
(backing vocals)and bracketed[ad-libs]text from LRCLIB lyrics as freestyle notes (Fprefix in UltraStar — displayed but not scored)Changes
is_freestyle,line_break_afterfieldsnote_type(:/F),line_break_afterfields_parse_reference_lyrics()with bracket parsing,_tokenize_with_parens()for(multi word)and[bracket]patternsnote_typeinstead of hardcodedNORMAL, prefer LRCLIB linebreaks over silence-based detectionTest plan
(backing vocals)— verifyFnotes in outputSummary by CodeRabbit
New Features
Tests