Skip to content

Preserve detected rests in generated audio and lyric accompaniment (#29) - #30

Merged
cchacs merged 2 commits into
mainfrom
pullfrog/29-preserve-detected-rests
Oct 11, 2026
Merged

cchacs merged 2 commits into
mainfrom
pullfrog/29-preserve-detected-rests

Conversation

@pullfrog

@pullfrog pullfrog Bot commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Closes #29.

Both chord sources dropped the end of each detected segment and emitted onset-only events, so _eventDuration sustained every generated chord until the next onset and filled the rests in between. This carries each segment's own end through detection and honors it during generation.

Changes

  • chordr/audio_chords.py — detect_chords_from_chroma now returns {"t", "name", "end"} per segment. end is the run's own end (the next frame's onset, or one frame past the last onset for a run reaching the end of the analysis), so internal and trailing silence in the input survives.
  • chordr/screen.js
    • _normaliseHarmonyEvents carries an optional end through to generation.
    • _eventDuration honors an explicit end instead of always holding to the next onset, clamped to the next onset and to lengthSeconds.
    • _harmonizeMelody emits end per window (min(winEnd, lastEnd)), so a silent window is a rest and the final window stops where the melody ends.
    • Authored chart chords without an end keep the existing next-onset behavior.

Tests

  • Python: internal silence is a gap (events[0].end at the silence, not the next onset) and trailing silence is preserved.
  • JS: explicit end stops a chord before the next onset; not extended by lengthSeconds; capped by lengthSeconds and the next onset; the audio path honors detected run ends; harmonization does not sustain across silent windows and stops at melody end.

Mutation-checked each new test against the old behavior to confirm it fails without the fix.

node --test tests/*.test.js → 106 pass; python3 -m unittest discover -s tests -p 'test_*.py' → 20 pass.

Docs (README, CHANGELOG, CLAUDE.md) updated and plugin.json bumped to 0.6.1.

Pullfrog  | View workflow run | via Pullfrog | Using big-pickle (free) | 𝕏

@kilo-code-bot

kilo-code-bot Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • CLAUDE.md — Test count updated (106→107)
  • chordr/screen.js — _eventDuration: when explicit end is present, honor measured duration exactly (bypass 100ms floor) while preserving clamping to next onset and lengthSeconds
  • tests/generate_arrangement.test.js — Regression test for sub-100ms explicit end
Previous Review Summary (commit 8506ea4)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 8506ea4)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (7 files)
  • chordr/audio_chords.py — Added end field to detected chord segments; correctly computes run end as next frame's onset or one frame past last onset
  • chordr/screen.js — _normaliseHarmonyEvents carries end through; _eventDuration honors explicit end with clamping to next onset and lengthSeconds; _harmonizeMelody emits end per window capped at melody end
  • tests/test_audio_chords.py — New tests for internal silence as rest and trailing silence preservation
  • tests/generate_arrangement.test.js — New tests for explicit end behavior: stops before next onset, not extended by lengthSeconds, capped at lengthSeconds/next onset, audio path honors run ends
  • tests/generate_accompaniment_from_lyrics.test.js — New tests for silent windows not sustained and accompaniment stopping at melody end
  • README.md, CHANGELOG.md, CLAUDE.md, chordr/plugin.json — Documentation and version bump

Reviewed by free · Input: 36.5K · Output: 1.9K · Cached: 115.4K

cchacs
cchacs previously requested changes Oct 11, 2026

@cchacs cchacs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs fixing: a 20 ms chord becomes 100 ms, extending into the rest. Reproduced from the actual function.

@pullfrog

pullfrog Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor Author

Fixed the reviewer's repro: _eventDuration was flooring every duration to 100 ms, so a detected/harmonized segment shorter than that (e.g. a 20 ms run) was stretched into the rest that follows it.

Change in chordr/screen.js: when an event carries an explicit end, the duration is now returned as end - start (still clamped to the next onset and to lengthSeconds), bypassing the 100 ms floor. The floor still applies to the derived-end path (next onset / trailing chord), where it originally belonged. Added a regression test asserting a 20 ms explicit end stays 20 ms.

Verified: node --test tests/*.test.js → 107 pass; python3 -m unittest discover -s tests -p 'test_*.py' → 20 pass. Pushed to the PR branch (732c06c).

Task list (6/6 completed)
  • Checkout PR branch
  • Fetch and read review comments
  • Verify findings against code
  • Implement fixes or reply
  • Test, review diff, commit
  • Push and reply to threads

Pullfrog  | View workflow run | via Pullfrog | Using big-pickle (free) | 𝕏

@cchacs
cchacs dismissed their stale review October 11, 2026 02:33

The previous finding is fixed: explicit 20 ms chords retain their duration, with a regression test added. No new blocking findings. Verified locally: 107 JavaScript tests and 20 Python tests passed.

@cchacs
cchacs merged commit 6ec19d3 into main Oct 11, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Preserve detected rests in generated audio and lyric accompaniment

1 participant