Skip to content

feat/sample editor - #21

Open
DavidMenting wants to merge 24 commits into
mainfrom
feat/sample-editor
Open

feat/sample editor#21
DavidMenting wants to merge 24 commits into
mainfrom
feat/sample-editor

Conversation

@DavidMenting

Copy link
Copy Markdown
Member
  • Rework sample recorder trim and controls
  • Dim tracks that do not hold the selected note
  • feat(midi): implement SDS download protocol and transfer locking
  • refactor(ui): clean up redundant controls and mount SettingsModal
  • i18n: add translations for settings modal and SDS downloads
  • feat(recorder): auto-download device sample on pad selection
  • ci: configure GitHub Actinos deployment to GitHub Pages

- Make the yellow trim bars in the waveform draggable (with center
  handle circles), replacing the horizontal start/end sliders
- Merge record and record-again into one round button left of the
  waveform; first press opens the microphone and records immediately,
  removing the separate turn-on-microphone button
- Keep play and save buttons always visible (disabled when unusable),
  play/save now sit right of the gain slider
- Add browse and factory-reset buttons next to the record button; both
  load audio into the capture buffer for trim/gain adjustment before
  saving to the device
- Extract FACTORY_SAMPLES map to shared config
- SampleCapture: add load() for external buffers, playback without an
  open mic stream, reset() falls back to idle
- Move mic selector below the buttons; drop unused locale keys
Pad selection now loads instantly from an in-memory cache (device
downloads, uploads, and preloaded factory samples). The ~1s SDS device
download on selection is gated behind a new 'downloadOnSelect' feature
flag (default off) so we can evaluate whether factory preload alone is
good enough.
Gives the device time to finish playing back the sample before the
transfer freezes the sequencer. The wait is abortable, so switching
pads during the delay cancels it immediately.
Timer handle in the browser isn't a number under this env's DOM lib config, causing a type-check error.
…napshots

prevSelectedSampleIndex/prevContainerWidthPx intentionally snapshot the initial value and are updated inside the effect below, which is the pattern Svelte's warning otherwise flags as a mistake.
Deduplicate the decode -> stereo-to-mono -> resample logic that lived in
both SampleRecorder.loadIntoBuffer and sampleCache.doPreload into a
single decodeToMono() in audioAnalysis. Factory samples now cache at
their native rate (rate is stored and consumers resample on load).
Remove the hidden mode switch in load() (adopt rate when no context,
throw on mismatch otherwise). load() now resamples any incoming rate to
capture.sampleRate itself, so callers no longer pre-resample by
convention.
Collapse the two near-identical load paths into one loadIntoEditor with
an explicit trim policy ('auto' | 'full'); file decoding and the
MAX_LOAD_S cap live in loadFileIntoEditor, the file-input wrapper.
downloadState no longer duplicates the sample data (nobody read it);
results flow through the downloadSample promise only. Caching a
completed download moves into the store, where download knowledge
belongs, instead of the recorder's effect.
…ader

Move the cache -> maybe-download -> maybe-load policy out of the
SampleRecorder $effect into a plain component-free function that can be
reasoned about and tested without mounting the component. The effect now
only detects slot changes and delegates.
…ckets

Two receive-path bugs:

- Messages arriving between waitForIncoming() calls were dropped (only a
  single one-shot resolver existed), causing spurious 2s timeouts when
  the device sends packets back-to-back. Incoming download messages are
  now queued when no waiter is armed and drained in order.

- expectedPacketNum was computed but never checked, so an out-of-order
  packet (other than an exact duplicate of the last) was silently written
  at the wrong buffer offset, corrupting the sample. Out-of-order packets
  are now NAKed with the expected packet number.

waitForIncoming is also abort-aware now: an AbortSignal resolves the wait
immediately with 'aborted' instead of blocking until the timeout.
downloadSample aborted the previous download and then immediately
checked isTransferActive() — but the aborted transfer only releases the
lock in its finally, which hadn't run yet, so rapid pad-switching made
the new download silently bail. The in-flight promise is now tracked and
awaited after abort (fast, since waits are abort-aware) before the lock
check.
lastLoadedSlot was set before the recording/isSaving guard, so a pad
selected mid-recording was permanently marked as loaded and never got
its sample loaded afterwards. The slot is now only marked once the load
actually proceeds.
- i18n the hardcoded Browse/Reset button labels in SampleRecorder
  (new recorder_browse/recorder_reset keys in en/de/nl)
- SettingsModal closes on Escape and backdrop click
- remove unused download_empty_slot/download_timeout locale keys
- remove dead downloadState import from Voice
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.

1 participant