From 2a27facd94166c21ffc00687875ad1b02eac417d Mon Sep 17 00:00:00 2001 From: ChrisBeWithYou Date: Sun, 5 Jul 2026 16:19:23 -0500 Subject: [PATCH 1/2] feat(editor): point users at Tempo Map when an import drifts from the audio Auto-sync can only approximate a human performance between sync points, so an imported GP chart often starts aligned and then drifts -- and the #1 confusion in the field is not realizing the beatmap is editable at all. The Tempo Map editor (drag sync points, per-measure BPM + time signature, insert/delete, drum-vs-all ride scope) already exists, but nobody finds it ("surprised you can't edit the beatmap"). Make the fix discoverable at the moment it's needed: the post-import status now names it for both the per-bar 'warp' and the scalar 'offset' fallback (repeats/jumps, degenerate anchors), ending with "Drifting from the recording? Open Tempo Map to drag the beat grid onto the audio." The toolbar button tooltip now reads "...fix a chart drifting from the audio -- drag the beat grid, edit BPM & time signatures." No change to the import or the Tempo Map editor itself. The message is extracted to the pure _syncAppliedMessagePure so it's unit-tested. All 25 editor JS test files pass. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01UR2Cr7GEu3yMY7SrfxH6c1 --- CHANGELOG.md | 3 +-- screen.js | 37 +++++++++++++++++++++----------- tests/tempo_map_guidance.test.js | 26 +++++++++++++++++++++- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c28b767..ce6a0008 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,8 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 can be removed in a follow-up. ### Changed -- **The audio lane now draws a real waveform.** It previously showed a - symmetric magnitude band (absolute-peak per bucket, mirrored about the +- **Point people at Tempo Map when an import drifts from the audio.** Auto-sync can only approximate a *human* performance between sync points, so an imported chart often starts aligned and then drifts (falls behind / gets ahead) — and the #1 confusion in the field is not realizing the **beatmap is editable at all**. The post-import status now names the fix in both cases: per-bar `warp` and the scalar `offset` fallback (GP3/4/5 repeats/jumps, degenerate anchors) each end with *"Drifting from the recording? Open 🎵 Tempo Map to drag the beat grid onto the audio."*, and the toolbar button's tooltip now reads "…fix a chart drifting from the audio — drag the beat grid, edit BPM & time signatures." No behavior change to the import itself; the Tempo Map editor (drag sync points, per-measure BPM + time signature, insert/delete, drum-vs-all ride scope) already existed. Tests: `tests/tempo_map_guidance.test.js` (`_syncAppliedMessagePure`). centre line), which hid the signal's actual shape and went blocky on zoom. It now renders the true signed **min→max peak envelope** with a brighter **RMS body** inside it (Audacity-style), built from a high-resolution diff --git a/screen.js b/screen.js index 17bdd658..8f846482 100644 --- a/screen.js +++ b/screen.js @@ -8911,17 +8911,12 @@ window.editorDoCreate = async () => { if (data.error) { status.textContent = 'Error: ' + data.error; btn.disabled = false; return; } await window.editorApplyCreateResult(data); - // Surface how the sync landed: 'warp' = chart follows the recording - // bar-by-bar; 'offset' = the server fell back to the scalar offset, - // with sync_reason saying why ('repeats' is the only user-actionable - // cause; everything else gets a generic message). - if (typeof setStatus === 'function' && data.sync_applied === 'warp') { - setStatus('Imported with per-bar audio sync.'); - } else if (typeof setStatus === 'function' && data.sync_applied === 'offset') { - setStatus(data.sync_reason === 'repeats' - ? 'This file uses repeats/jumps, which per-bar sync can’t map yet — applied start offset only.' - : 'Per-bar sync could not be applied to this import — applied start offset only.'); - } + // Surface how the sync landed ('warp' = chart follows the recording + // bar-by-bar; 'offset' = server fell back to the scalar offset), and — + // for either — point the user at the Tempo Map editor to fine-tune any + // residual drift by hand. See _syncAppliedMessagePure. + const _syncMsg = _syncAppliedMessagePure(data.sync_applied, data.sync_reason); + if (_syncMsg && typeof setStatus === 'function') setStatus(_syncMsg); } catch (e) { status.textContent = 'Import failed: ' + e.message; btn.disabled = false; @@ -11624,6 +11619,24 @@ function _tempoMapHudTextPure(measureCount, width) { } return `Tempo Map - ${n} measures - drag poles to retime - right-click sync point: BPM / signature/delete - right-click grid: insert`; } +// Status shown right after an audio-synced GP import. Names the Tempo Map tool +// so a drifting chart has an obvious, discoverable fix — the #1 confusion in the +// field is not knowing the beatmap is editable at all (auto-sync can only +// approximate a human performance between sync points, so some drift is +// expected and is meant to be fine-tuned by hand). +function _syncAppliedMessagePure(syncApplied, syncReason) { + const tip = ' Drifting from the recording? Open 🎵 Tempo Map to drag the beat grid onto the audio.'; + if (syncApplied === 'warp') { + return 'Imported with per-bar audio sync.' + tip; + } + if (syncApplied === 'offset') { + const base = syncReason === 'repeats' + ? 'This file uses repeats/jumps, which per-bar sync can’t map yet — applied start offset only.' + : 'Per-bar sync could not be applied to this import — applied start offset only.'; + return base + tip; + } + return ''; +} /* @pure:tempo-map-guidance:end */ /* @pure:tempo-sync-inspector:start */ @@ -11794,7 +11807,7 @@ function _ensureTempoMapButton() { btn.type = 'button'; btn.textContent = '🎵 Tempo Map'; btn.className = 'px-3 py-1 bg-dark-600 hover:bg-dark-500 rounded text-xs font-medium hidden'; - btn.title = 'Open Tempo Map to edit sync points, BPM, and time signatures'; + btn.title = 'Open Tempo Map to fix a chart drifting from the audio — drag the beat grid, edit BPM & time signatures'; btn.onclick = () => { // Finalize any in-progress canvas drag before switching // modes — commit a moved sync-point / drum drag (don't diff --git a/tests/tempo_map_guidance.test.js b/tests/tempo_map_guidance.test.js index 42f0580b..11630ca1 100644 --- a/tests/tempo_map_guidance.test.js +++ b/tests/tempo_map_guidance.test.js @@ -16,7 +16,7 @@ if (!m) { } const api = new Function( - '"use strict";' + m[0] + '\nreturn { _tempoMapHudTextPure };' + '"use strict";' + m[0] + '\nreturn { _tempoMapHudTextPure, _syncAppliedMessagePure };' )(); let pass = 0; @@ -46,5 +46,29 @@ t('normalizes invalid measure counts to zero', () => { assert.ok(api._tempoMapHudTextPure('bad', 960).includes('0 measures')); }); +t('warp import message points at the Tempo Map fine-tune path', () => { + const text = api._syncAppliedMessagePure('warp', null); + assert.ok(text.includes('per-bar audio sync')); + assert.ok(text.includes('Tempo Map')); + assert.ok(/drift/i.test(text)); +}); + +t('offset (repeats) message explains the fallback and points at Tempo Map', () => { + const text = api._syncAppliedMessagePure('offset', 'repeats'); + assert.ok(/repeats\/jumps/.test(text)); + assert.ok(text.includes('Tempo Map')); +}); + +t('offset (other) message is generic and points at Tempo Map', () => { + const text = api._syncAppliedMessagePure('offset', 'anchors'); + assert.ok(text.includes('could not be applied')); + assert.ok(text.includes('Tempo Map')); +}); + +t('no message when no audio sync was applied', () => { + assert.strictEqual(api._syncAppliedMessagePure(undefined, undefined), ''); + assert.strictEqual(api._syncAppliedMessagePure('', ''), ''); +}); + console.log(`\n${pass} passed, ${fail} failed`); process.exit(fail ? 1 : 0); From 386341d8b1e98be0e36d5676fdaceae4278b5a45 Mon Sep 17 00:00:00 2001 From: byrongamatos Date: Sun, 5 Jul 2026 23:52:38 +0200 Subject: [PATCH 2/2] docs: restore the waveform CHANGELOG entry split by the Tempo Map bullet The Tempo Map discoverability bullet was pasted over the 'real waveform' entry's header + first sentence. Restore the waveform entry and keep the Tempo Map note as its own bullet. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce6a0008..d03a0e25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,13 +53,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 can be removed in a follow-up. ### Changed -- **Point people at Tempo Map when an import drifts from the audio.** Auto-sync can only approximate a *human* performance between sync points, so an imported chart often starts aligned and then drifts (falls behind / gets ahead) — and the #1 confusion in the field is not realizing the **beatmap is editable at all**. The post-import status now names the fix in both cases: per-bar `warp` and the scalar `offset` fallback (GP3/4/5 repeats/jumps, degenerate anchors) each end with *"Drifting from the recording? Open 🎵 Tempo Map to drag the beat grid onto the audio."*, and the toolbar button's tooltip now reads "…fix a chart drifting from the audio — drag the beat grid, edit BPM & time signatures." No behavior change to the import itself; the Tempo Map editor (drag sync points, per-measure BPM + time signature, insert/delete, drum-vs-all ride scope) already existed. Tests: `tests/tempo_map_guidance.test.js` (`_syncAppliedMessagePure`). +- **The audio lane now draws a real waveform.** It previously showed a + symmetric magnitude band (absolute-peak per bucket, mirrored about the centre line), which hid the signal's actual shape and went blocky on zoom. It now renders the true signed **min→max peak envelope** with a brighter **RMS body** inside it (Audacity-style), built from a high-resolution per-bin min/max/RMS cache (~3 ms/bin) and aggregated per pixel column so the shape stays sharp at any zoom. Same lane, same seek behaviour — no layout or API change. Pure helper `_buildWaveformPeaks` covered by tests. +- **Point people at Tempo Map when an import drifts from the audio.** Auto-sync can only approximate a *human* performance between sync points, so an imported chart often starts aligned and then drifts (falls behind / gets ahead) — and the #1 confusion in the field is not realizing the **beatmap is editable at all**. The post-import status now names the fix in both cases: per-bar `warp` and the scalar `offset` fallback (GP3/4/5 repeats/jumps, degenerate anchors) each end with *"Drifting from the recording? Open 🎵 Tempo Map to drag the beat grid onto the audio."*, and the toolbar button's tooltip now reads "…fix a chart drifting from the audio — drag the beat grid, edit BPM & time signatures." No behavior change to the import itself; the Tempo Map editor (drag sync points, per-measure BPM + time signature, insert/delete, drum-vs-all ride scope) already existed. Tests: `tests/tempo_map_guidance.test.js` (`_syncAppliedMessagePure`). ### Added - **Import a Guitar Pro guitar/bass track into the song you're editing —