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
5 changes: 2 additions & 3 deletions PLANS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +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. #39 WAV file import as audio clip -> `docs/features/15-wav-file-import-as-audio-clip.md`
2. #41 Arrangement clip placement and playback -> `docs/features/16-arrangement-clip-placement-and-playback.md`
3. #43 Mixer audio routing and track controls -> `docs/features/17-mixer-audio-routing-and-track-controls.md`
1. #41 Arrangement clip placement and playback -> `docs/features/16-arrangement-clip-placement-and-playback.md`
2. #43 Mixer audio routing and track controls -> `docs/features/17-mixer-audio-routing-and-track-controls.md`

## Planned Milestones

Expand Down
4 changes: 4 additions & 0 deletions docs/audio-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Arrangement playback should:

The first arrangement playback implementation may play linearly from tick 0 through the end of the last placed clip instance, then stop. Arrangement loop regions can be added later.

The current first pass reuses the existing lookahead loop scheduler for `SONG` mode by setting a loop range that covers the visible arrangement. This keeps scheduling independent from React and enables pause/resume with the existing transport API, but it is not yet a true one-shot linear song transport. A later transport task should add non-looping arrangement playback that stops at the arrangement end.

The arrangement view may set loop start and loop end at bar boundaries. `SONG` playback should pass those ticks as the scheduler `loopStartTick` and `loopEndTick`. Selecting clips or instruments in the sidebar while `SONG` mode is playing must not replace the active arrangement scheduler with selected-clip `PAT` events.

Imported audio clips should play at original speed unless a later time-stretching feature explicitly changes that behavior. If an audio clip instance is shorter than the source buffer, playback should be cropped. If the instance is longer than the source buffer, playback may end naturally and leave silence. If runtime file data is missing after refresh, the engine should report a clear missing-source error rather than silently failing.

Arrangement playback still uses the lookahead scheduler. UI drag state, arrangement DOM geometry, visual playheads, decoded buffers, and active source nodes remain runtime-only.
Expand Down
13 changes: 13 additions & 0 deletions docs/data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@ The arrangement view places reusable clips on tracks using `ClipInstance` object
- How long the placed instance lasts in arrangement ticks.
- Optional source offset for audio clips.

`ArrangementLoopRange` owns the current song playback loop boundaries:

- Loop start tick.
- Loop end tick.
- Boundaries should snap to 4/4 bar boundaries in the first implementation.

Illustrative shape:

```ts
Expand All @@ -169,10 +175,17 @@ export interface ClipInstance {
lengthTicks: Tick;
sourceOffsetSeconds?: number;
}

export interface ArrangementLoopRange {
startTick: Tick;
endTick: Tick;
}
```

The first arrangement placement feature should create, move, select, and delete `ClipInstance` objects without mutating the source `Clip`. Deleting a placed clip from the arrangement removes only that instance. It does not delete the sidebar clip.

The first implementation keeps arrangement tracks, clip instances, and loop range in app-level state. The data is still serializable and should map directly into future `Project.tracks`, `Project.clipInstances`, and arrangement transport fields when export/import is implemented.

Default instance lengths:

- Hybrid clip: use the source clip's `lengthTicks`, initially 1920 ticks for a 1-bar clip.
Expand Down
12 changes: 10 additions & 2 deletions docs/features/16-arrangement-clip-placement-and-playback.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Feature: 16 Arrangement Clip Placement and Playback

## Status
Planned
In Review

## Goal

Expand Down Expand Up @@ -33,6 +33,7 @@ Included:
- Select and delete placed clip instances.
- Keep the existing arrangement track list and timeline layout aligned.
- Add a visual arrangement playhead in `SONG` mode.
- Let users set arrangement loop start and loop end on bar boundaries.
- Make transport play, pause, resume, and stop operate on arrangement playback when `SONG` mode is active.
- Schedule placed hybrid clips by expanding their drum and note events relative to each `ClipInstance.startTick`.
- Schedule placed audio clips when imported audio runtime data is available.
Expand Down Expand Up @@ -99,7 +100,7 @@ Use the existing `SONG` arrangement layout:
- Placed clips render as timeline blocks.
- Dragging a placed clip moves it to another snapped start time or track.
- Selecting a placed clip shows a clear selected state.
- Deleting a placed clip instance removes only that arrangement placement, not the source clip from the sidebar.
- Right-clicking a placed clip instance deletes only that arrangement placement, not the source clip from the sidebar.

Snap should start simple. Prefer beat-level snapping, using 480 ticks, unless the existing arrangement snap control already supports a narrower value. Later features may add user-selectable snap resolution.

Expand All @@ -109,6 +110,8 @@ If browser drag-and-drop is awkward for track timeline geometry, pointer-based d

`SONG` playback should schedule arrangement events, not selected-clip loop events.

Selecting a sidebar clip or instrument while `SONG` mode is playing should only change UI selection. It must not replace active arrangement playback with selected `PAT` clip events or stop playback just because an imported audio clip was selected.

The audio engine or feature orchestration should expand clip instances into runtime scheduler events:

- Hybrid clip drum events: `instance.startTick + drumEvent.startTick`.
Expand All @@ -117,6 +120,10 @@ The audio engine or feature orchestration should expand clip instances into runt

The arrangement transport may initially play linearly from tick 0 through the end of the last clip instance and then stop. Arrangement loop ranges can be added later.

The first implementation may reuse the existing lookahead loop scheduler over the visible arrangement range while the arrangement-specific one-shot/linear transport matures. If so, document the limitation in the PR and keep the arrangement event expansion independent from React.

When an arrangement loop range is set, `SONG` playback should use that range for `loopStartTick` and `loopEndTick`.

Events already scheduled inside the lookahead window may still play briefly after edits, pause, or stop. Keep the scheduling window short enough for interactive editing.

## Done when
Expand All @@ -130,6 +137,7 @@ Events already scheduled inside the lookahead window may still play briefly afte
- `SONG` transport playback schedules placed clip instances.
- Pause, resume, and stop work in `SONG` mode.
- A visual arrangement playhead follows playback and resets or hides appropriately when stopped.
- Loop start and loop end can be set on bar boundaries and `SONG` playback loops that range.
- Hybrid clip drum and note events play at their arrangement positions.
- Audio clip instances play when runtime imported audio data is available.
- Missing imported audio runtime data is reported clearly instead of silently failing.
Expand Down
6 changes: 5 additions & 1 deletion docs/ui-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ Track headers, timeline lanes, and clip blocks must align exactly. Use shared ge

Do not introduce real arrangement data, persisted clip instances, arrangement playback, or drag-and-drop editing in the first arrangement UI shell unless a feature spec explicitly expands the scope.

The arrangement placement feature expands this shell into an editable first pass. Static demo clip blocks should be removed once real `ClipInstance` state is available.

## Arrangement Clip Placement

The next arrangement step should make the `SONG` view editable and playable.
Expand All @@ -122,8 +124,10 @@ The next arrangement step should make the `SONG` view editable and playable.
- Dropping a clip creates a visible clip block backed by a serializable `ClipInstance`.
- Moving a clip block updates `startTick` and `trackId`, not stored pixel positions.
- Selecting a clip block should show a clear selected state.
- Deleting a selected clip block removes only the arrangement instance, not the source clip in the sidebar.
- Right-clicking a clip block deletes only that arrangement instance, not the source clip in the sidebar.
- Static demo clip blocks should be removed or replaced with seeded serializable state.
- The arrangement ruler may expose draggable loop start and loop end handles snapped to bar boundaries.
- The timeline should show loop start/end boundary lines. Avoid filling the full loop range across tracks; a small ruler connector between the loop handles is enough.

Use shared arrangement geometry constants for row height, ruler height, bar width, beat width, timeline width, and track header width. Inline styles are acceptable for dynamic clip geometry such as `left`, `top`, `width`, and transform values.

Expand Down
Loading
Loading