Sample Library Browser, Step Sequencer, MIDI, Sample Recording, Effects Rack - #3
Open
ResistanceIsUseless wants to merge 13 commits into
Open
ResistanceIsUseless wants to merge 13 commits into
ResistanceIsUseless wants to merge 13 commits into
Conversation
…quencer Three major features built on top of the MPC Sample desktop app: - Sample Library Browser: scan/browse/preview/tag/drag-to-pad for large local sample folders. Scanning and waveform decode run in the Electron main process so the UI never blocks, with a disk cache keyed by path+size+mtime and a restricted mpc-sample:// protocol for streaming preview/export without loading whole files into renderer memory. Also fixes playback of WAVs with a trailing RIFF LIST/INFO chunk (FL Studio export quirk) that was corrupting the served byte range. - Bidirectional MIDI: fixed hardware input (the MPC Sample shifts its outgoing note number by 16 per physical pad bank; the app only accepted notes 36-51, silently dropping every bank past A) and added MIDI output so UI-triggered pad hits echo back to the physical device (MidiInput now also implements MidiOutputLike; store.triggerPad/releasePad take a fromHardware flag to avoid echoing hardware-originated hits back out). - Step sequencer (v1, live/MIDI-driven): program pad hits on a configurable bar/resolution step grid, played back via Tone.Transport through the existing engine + MIDI-out path. Click-to-preview on step activation, scroll-to-adjust per-step velocity, and pattern persistence to localStorage. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Reverse-engineered the real event schema from a user-recorded .xpj project (note events live per-track at sequences[].value.trackClipMaps[0][entryIdx].value.eventList.events, 960 ticks/beat, note = padIdx + 36) and wired the step sequencer's pattern into the existing kit-export pipeline so it shows up as a real, editable sequence on the hardware instead of only playing back live from the app. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Panels can be dragged by their header to anywhere in the window (pointer-drag, matching the existing Knob/PitchFader idiom; double-click resets to the docked position), composing a --drag-x/--drag-y translate on top of each panel's existing slide-open/centering transform rather than fighting it. The bottom-left HUD can be hidden/restored via a small persistent tab, with hudVisible persisted alongside the other UI settings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Uses Electron's session.setDisplayMediaRequestHandler with useSystemPicker: true so getDisplayMedia triggers macOS's own ScreenCaptureKit-backed picker — pick a specific window (a browser tab, VLC, Plex) and capture just its audio. Recording taps a dedicated native AudioContext via a ScriptProcessorNode (discovered live that Tone.getContext().rawContext is actually Tone's standardized-audio-context wrapper, which doesn't implement createScriptProcessor), encodes to 16-bit PCM WAV with a new hand-rolled encoder, and offers a waveform preview + click-to-assign pad picker before committing the take. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ture getDisplayMedia() worked, but every recording attempt failed with NotAllowedError: Permission denied even after granting Screen Recording in System Settings. Root-caused live (via CDP against the packaged app) by logging every permission string Electron actually checked: Chromium gates the getDisplayMedia() call itself on "display-capture", but separately checks "media" to grant use of the resulting audio track — and only "display-capture" was allow-listed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two more bugs found and fixed after the permission fix, both root-caused live via Chrome DevTools Protocol attached directly to the packaged app: 1. useSystemPicker's native macOS picker never actually returns an audio track (confirmed: electron/electron#44685, still open). Dropped it entirely in favor of granting audio: "loopback" directly in handleDisplayMediaRequest — capture is now always system-wide (no more per-window picker UI). 2. The direct loopback grant then returned an audio track that looked successful but was silently dead (readyState: "ended", zero signal, no error) — recent Chromium defaults to Apple's new CoreAudio Tap API for macOS loopback, which needs a different, newly-introduced Info.plist key (NSAudioCaptureUsageDescription) almost nothing has yet, and fails with no fallback when it's missing (electron/electron#49607). Fixed by explicitly disabling that path via disable-features: MacCatapLoopbackAudioForScreenShare. Confirmed with real captured audio (readyState: "live", strong RMS signal) and end-to-end through the actual UI: record, stop, waveform preview, pad assignment, playback from that pad. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
getDisplayMedia's `audio: true` shorthand defaults echoCancellation, noiseSuppression, and autoGainControl all to true, and channelCount to mono — even for system-audio loopback. Those are voice-call DSP tuned for mic input; applied to music/video they genuinely mangle the signal. Confirmed numerically with a clean 440Hz test tone: with the defaults on, the captured signal measured 431.5Hz with amplitude drift and discontinuities; with echoCancellation/noiseSuppression/ autoGainControl explicitly disabled and channelCount:2 requested, it measured an exact 440.0Hz with a flat RMS envelope and zero discontinuities. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…iles - Find the MPC SD card by scanning /Volumes for MPC-Sample/Projects (any volume name, e.g. SDCARD) instead of hardcoding MPC-SD; eject uses it too. - Shrink waveform peaks from 600 to 72 points (thumbnail is 72px). The old cache hit ~526 MB on a 25k-sample library, exceeding V8's max string length. Stale-format cache entries are re-decoded. - Batch library decode progress into one store update per 250 ms instead of rebuilding the entry list per file. - Hide unreadable/corrupt audio files from the Sample Browser. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The renderer is served from http://localhost in dev, making fetch() of mpc-sample:// cross-origin. Register the scheme with corsEnabled and send Access-Control-Allow-Origin on audio responses. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… pass The hardware forces add-effect -> resample -> add-next-effect per stacked effect. Firmware research found no MIDI/USB control surface over the effects engine to automate that remotely (see mpc-firmware-research: the device's /api/v1 API is real but gated behind on-device PIN pairing). Built an in-app workaround instead: a chain of filter/distortion/ bitcrusher/chorus/delay/reverb that renders through Tone.Offline in a single pass and writes the result back onto the pad as a new sample. - src/audio/effects.types.ts: plain, serializable EffectInstance chain. - src/audio/effectsChain.ts: renderEffectsChain (offline) and previewEffectsChain (realtime audition) share one node-building path. - src/components/EffectsRackPanel.tsx: new panel, opened via an "Effects..." button in KitEditor's per-pad editor. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cover everything built on this branch: sample library browser (25k+ files), auto-tagging, step sequencer with native .xpj export, system-audio sample recording, the offline effects rack, MIDI in/out, and the direct unzipped SD card workflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-browser Sample Library Browser, Step Sequencer, MIDI, Sample Recording, Effects Rack
|
@ResistanceIsUseless is attempting to deploy a commit to the World Link Studio Team on Vercel. A member of the Team first needs to authorize it. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sample Library Browser, Step Sequencer, MIDI, Sample Recording, Effects Rack
Adds a sample library browser for large local sample collections, bidirectional MIDI control, a step sequencer with native
.xpjexport, system-audio sample recording, an offline multi-effect rack, and a more reliable SD card export workflow.Sample Library Browser
MIDI
Step Sequencer
Sample Recording
Effects Rack
Desktop / SD Card Workflow
.xpj+_[ProjectData]/*.wav) — no zip/unzip round-tripTesting
npm run typecheckandnpm testpass (main + Electron test configs)🤖 Generated with Claude Code