|
| 1 | +# Feature: 07 Transport Pause and Playhead |
| 2 | + |
| 3 | +## Status |
| 4 | +Planned |
| 5 | + |
| 6 | +## Goal |
| 7 | + |
| 8 | +Implement distinct pause, resume, and stop behavior for clip playback, and render a vertical runtime playhead in clip editors. |
| 9 | + |
| 10 | +## Context |
| 11 | + |
| 12 | +The current transport has only `playing` and `stopped` states. The play button can show a pause icon while playback is active, but pressing it stops playback in the same way as the stop button. |
| 13 | + |
| 14 | +Before piano roll playback and hybrid clip loop playback become more complex, the app needs a clearer runtime transport model: |
| 15 | + |
| 16 | +- Play from stopped starts at the beginning of the selected 1-bar clip. |
| 17 | +- Pause stops playback while preserving the current musical tick. |
| 18 | +- Resume continues from the paused tick. |
| 19 | +- Stop stops playback and resets the playhead to the beginning. |
| 20 | + |
| 21 | +The visual playhead helps users understand where sequenced drum and note events are playing. It must not become the timing source for audio playback. |
| 22 | + |
| 23 | +## Scope |
| 24 | + |
| 25 | +Included: |
| 26 | +- Add a `paused` transport state. |
| 27 | +- Track the current runtime playhead position in ticks. |
| 28 | +- Capture the current tick when pausing. |
| 29 | +- Resume playback from the paused tick. |
| 30 | +- Stop playback and reset the runtime playhead to tick 0. |
| 31 | +- Render a vertical playhead in the piano roll editor. |
| 32 | +- Render a playhead in the drum step sequencer if practical for the same implementation pass. |
| 33 | +- Keep visual playhead animation driven by `requestAnimationFrame`. |
| 34 | +- Keep exact audio scheduling driven by `AudioContext.currentTime`. |
| 35 | +- Add focused tests for transport tick calculations, pause/resume offsets, and loop wrapping where practical. |
| 36 | +- Update relevant docs if the audio engine API or transport state model changes. |
| 37 | + |
| 38 | +Excluded: |
| 39 | +- Arrangement timeline playhead. |
| 40 | +- Timeline scrubbing. |
| 41 | +- Realtime recording. |
| 42 | +- Automation. |
| 43 | +- Tempo automation. |
| 44 | +- Persisting runtime playhead position in project JSON. |
| 45 | +- Full transport keyboard shortcut support. |
| 46 | + |
| 47 | +## Constraints |
| 48 | + |
| 49 | +- Store musical position in ticks, not seconds. |
| 50 | +- Use PPQ 480, with the M1 1-bar loop spanning ticks 0 through 1920. |
| 51 | +- Treat the paused playhead position as runtime state, not serializable project data. |
| 52 | +- Do not store `AudioContext`, `AudioBuffer`, scheduler timers, source nodes, or playhead timers in project JSON. |
| 53 | +- React UI may display transport state and playhead position, but must not own exact audio timing. |
| 54 | +- The audio engine and scheduler must remain independent from React components. |
| 55 | +- The visual playhead may be approximate; audible event timing must remain scheduled against `AudioContext.currentTime`. |
| 56 | +- Use CSS Modules and semantic design tokens for playhead styling. |
| 57 | +- Inline styles are acceptable for computed playhead geometry, such as `transform`, `left`, or width derived from ticks. |
| 58 | + |
| 59 | +## Done when |
| 60 | + |
| 61 | +- Transport state can represent `stopped`, `playing`, and `paused`. |
| 62 | +- Pressing play from stopped starts playback from tick 0. |
| 63 | +- Pressing pause while playing stops scheduling and preserves the current playhead tick. |
| 64 | +- Pressing play from paused resumes playback from the paused tick. |
| 65 | +- Pressing stop from playing or paused stops playback and resets the playhead to tick 0. |
| 66 | +- The piano roll displays a vertical playhead aligned to the 1-bar grid. |
| 67 | +- The playhead wraps cleanly at the 1-bar loop boundary. |
| 68 | +- If included, the drum step sequencer displays a playhead or equivalent step-position indicator aligned to the 16-step grid. |
| 69 | +- Existing drum step playback behavior still works. |
| 70 | +- Tests cover pure transport/tick math where practical. |
| 71 | + |
| 72 | +## Verification |
| 73 | +Run: |
| 74 | +- `npm run typecheck` |
| 75 | +- `npm run lint` |
| 76 | +- `npm run test` |
| 77 | +- `npm run build` |
| 78 | + |
| 79 | +Manual check: |
| 80 | +- Start playback from stopped and confirm the playhead starts at the beginning. |
| 81 | +- Pause playback and confirm the playhead stops at its current position. |
| 82 | +- Resume playback and confirm it continues from the paused position. |
| 83 | +- Stop playback and confirm the playhead returns to the beginning. |
| 84 | +- Confirm the visual playhead loops across the 1-bar clip without jumping outside the editor grid. |
| 85 | +- Confirm drum steps still trigger at the expected musical positions after pause/resume. |
| 86 | + |
| 87 | +## PR notes |
| 88 | +- Describe the transport state model and runtime tick fields added or changed. |
| 89 | +- Explain how pause differs from stop. |
| 90 | +- Explain how the visual playhead reads timing state without driving audio scheduling. |
| 91 | +- Note whether drum sequencer playhead display was included or deferred. |
0 commit comments