Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions PLANS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ M1 should include:

Use this section as the current execution order for agent work. Feature document numbering describes the planned product sequence, but actual issue order may change as dependencies, review feedback, or implementation risks become clearer.

1. #3 Drum Step Sequencer -> `docs/features/04-drum-step-sequencer.md` (PR #15 in review)
2. #2 Basic Piano Roll -> `docs/features/05-basic-piano-roll.md`
1. #2 Basic Piano Roll -> `docs/features/05-basic-piano-roll.md`
2. #16 Transport pause/resume and editor playhead -> `docs/features/07-transport-pause-and-playhead.md`

## Planned Milestones

Expand All @@ -39,13 +39,14 @@ Use this section as the current execution order for agent work. Feature document
3. Lookahead scheduler.
4. Drum step sequencer.
5. Basic piano roll.
6. Hybrid clip loop playback.
7. Sample import.
8. Project export/import.
9. IndexedDB autosave.
10. Arrangement data model.
11. Arrangement view.
12. Mixer and basic effects.
6. Transport pause/resume and editor playhead.
7. Hybrid clip loop playback.
8. Sample import.
9. Project export/import.
10. IndexedDB autosave.
11. Arrangement data model.
12. Arrangement view.
13. Mixer and basic effects.

## Backlog

Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The main rule is separation of concerns: UI rendering, persistence, and audio sc

- Render the transport, clip editor, drum sequencer, piano roll, and later arrangement views.
- Dispatch user actions to state/model logic.
- Display audio state such as playing/stopped and playhead position.
- Display audio state such as stopped, playing, paused, and playhead position.
- Use `requestAnimationFrame` for visual playheads where needed.
- Avoid owning exact audio timing.

Expand Down
10 changes: 9 additions & 1 deletion docs/audio-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ The documented default is PPQ 480. In 4/4, one bar is 1920 ticks and one 16-step

Transport state should include:

- Playing or stopped state.
- Playback state: `stopped`, `playing`, or `paused`.
- Tempo in BPM.
- Current tick.
- Audio start time.
Expand All @@ -82,6 +82,12 @@ Transport state should include:

Transport state may be mirrored into React for display, but React render timing must not drive exact audio playback.

Pause and stop have different meanings:

- Pause captures the current runtime playhead tick and stops future scheduling. Resume should continue from that tick.
- Stop clears scheduling and resets the runtime playhead tick to the loop start, which is tick 0 for the M1 1-bar clip.
- The paused playhead position is runtime state only. It should not be written to project JSON.

## Looping Behavior

For M1, loop playback targets a selected 1-bar clip. The default loop range is 0 to 1920 ticks.
Expand All @@ -96,6 +102,8 @@ When the user edits a drum pattern during playback, the UI may update the schedu

UI cursor and playhead animation may use `requestAnimationFrame` and read transport position from the audio engine. Visual playhead timing can be approximate. Exact sound timing must come from scheduled Web Audio events.

The UI may render a vertical playhead over the piano roll or drum sequencer by converting the current runtime tick into editor geometry. The playhead should wrap at the active loop boundary. It is display feedback only; moving or rendering the playhead must not be required for audio events to play on time.

## Future Extension Points

- Sampler instrument.
Expand Down
2 changes: 1 addition & 1 deletion docs/features/04-drum-step-sequencer.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Feature: 04 Drum Step Sequencer

## Status
In Review
Done

## Goal

Expand Down
2 changes: 1 addition & 1 deletion docs/features/06-main-daw-ui-shell.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Feature: 06 Main DAW UI Shell

## Status
In Review
Done

## Goal

Expand Down
91 changes: 91 additions & 0 deletions docs/features/07-transport-pause-and-playhead.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Feature: 07 Transport Pause and Playhead

## Status
Planned

## Goal

Implement distinct pause, resume, and stop behavior for clip playback, and render a vertical runtime playhead in clip editors.

## Context

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.

Before piano roll playback and hybrid clip loop playback become more complex, the app needs a clearer runtime transport model:

- Play from stopped starts at the beginning of the selected 1-bar clip.
- Pause stops playback while preserving the current musical tick.
- Resume continues from the paused tick.
- Stop stops playback and resets the playhead to the beginning.

The visual playhead helps users understand where sequenced drum and note events are playing. It must not become the timing source for audio playback.

## Scope

Included:
- Add a `paused` transport state.
- Track the current runtime playhead position in ticks.
- Capture the current tick when pausing.
- Resume playback from the paused tick.
- Stop playback and reset the runtime playhead to tick 0.
- Render a vertical playhead in the piano roll editor.
- Render a playhead in the drum step sequencer if practical for the same implementation pass.
- Keep visual playhead animation driven by `requestAnimationFrame`.
- Keep exact audio scheduling driven by `AudioContext.currentTime`.
- Add focused tests for transport tick calculations, pause/resume offsets, and loop wrapping where practical.
- Update relevant docs if the audio engine API or transport state model changes.

Excluded:
- Arrangement timeline playhead.
- Timeline scrubbing.
- Realtime recording.
- Automation.
- Tempo automation.
- Persisting runtime playhead position in project JSON.
- Full transport keyboard shortcut support.

## Constraints

- Store musical position in ticks, not seconds.
- Use PPQ 480, with the M1 1-bar loop spanning ticks 0 through 1920.
- Treat the paused playhead position as runtime state, not serializable project data.
- Do not store `AudioContext`, `AudioBuffer`, scheduler timers, source nodes, or playhead timers in project JSON.
- React UI may display transport state and playhead position, but must not own exact audio timing.
- The audio engine and scheduler must remain independent from React components.
- The visual playhead may be approximate; audible event timing must remain scheduled against `AudioContext.currentTime`.
- Use CSS Modules and semantic design tokens for playhead styling.
- Inline styles are acceptable for computed playhead geometry, such as `transform`, `left`, or width derived from ticks.

## Done when

- Transport state can represent `stopped`, `playing`, and `paused`.
- Pressing play from stopped starts playback from tick 0.
- Pressing pause while playing stops scheduling and preserves the current playhead tick.
- Pressing play from paused resumes playback from the paused tick.
- Pressing stop from playing or paused stops playback and resets the playhead to tick 0.
- The piano roll displays a vertical playhead aligned to the 1-bar grid.
- The playhead wraps cleanly at the 1-bar loop boundary.
- If included, the drum step sequencer displays a playhead or equivalent step-position indicator aligned to the 16-step grid.
- Existing drum step playback behavior still works.
- Tests cover pure transport/tick math where practical.

## Verification
Run:
- `npm run typecheck`
- `npm run lint`
- `npm run test`
- `npm run build`

Manual check:
- Start playback from stopped and confirm the playhead starts at the beginning.
- Pause playback and confirm the playhead stops at its current position.
- Resume playback and confirm it continues from the paused position.
- Stop playback and confirm the playhead returns to the beginning.
- Confirm the visual playhead loops across the 1-bar clip without jumping outside the editor grid.
- Confirm drum steps still trigger at the expected musical positions after pause/resume.

## PR notes
- Describe the transport state model and runtime tick fields added or changed.
- Explain how pause differs from stop.
- Explain how the visual playhead reads timing state without driving audio scheduling.
- Note whether drum sequencer playhead display was included or deferred.
3 changes: 3 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ tests/unit/utils/tick-time.test.ts

- Tick-to-seconds conversion.
- Loop boundaries.
- Pause/resume tick offsets.
- Playhead wrapping at loop boundaries.
- Clip duplication.
- Sample import.
- Project export/import.
Expand All @@ -56,6 +58,7 @@ Manual audio checks should verify:
- One-shot samples play repeatedly without reusing the same source node.
- Loop playback does not double-trigger events at the loop boundary.
- UI playhead movement roughly matches audible playback.
- Pause preserves the runtime playhead position, resume continues from that position, and stop resets to the start.
- Starting, stopping, and restarting transport leaves no stuck sounds.
- Tempo changes behave as documented for the current milestone.

Expand Down
11 changes: 11 additions & 0 deletions docs/ui-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,17 @@ Inline styles are acceptable for computed editor geometry, including:

Keep static appearance in CSS Modules. Keep dynamic numeric layout derived from ticks, pitch, and grid dimensions.

## Playhead Display

Clip editors may render a vertical playhead to show the current runtime transport position.

- The playhead position should be derived from tick position and editor dimensions.
- Use `requestAnimationFrame` for visual updates when playback is active.
- Keep the playhead as visual feedback only; it must not drive exact audio scheduling.
- Use CSS Modules and semantic design tokens for static playhead styling.
- Inline styles are acceptable for computed playhead geometry such as `left` or `transform`.
- When stopped, the playhead should reset to the start of the selected clip. When paused, it should remain at the paused tick.

## Sample Display Names

When displaying bundled drum sample names in the UI, derive the label from the `.wav` file name:
Expand Down
Loading