Files
feuerwerk/tools
adminandClaude Opus 5.5 144dee0a97 Let a looped sample play out past its loop when the note ends #331
With "Mode" and "Loop" as two fields, One-shot plus Loop ran until
Stop was pressed: letting go of the key did nothing. The two fields
are now one, "Play", with four entries that each say what happens
while the note is held and when it is let go.

- Gate and One-shot play the sound once, as before. Loop repeats it
  and fades out with the note.
- "Loop, then release" is new: the sampler's sustain loop. Let go,
  it finishes the round it is in and plays what comes after "Loop
  end" to the end of the sound.
- A buffer source stops looping and plays on by itself. The pitch
  worklet gets a "leave" message. The phase vocoder then lets the
  round finish that its newest frame has read into, so nothing read
  already changes under the frames still sounding.
- Samples saved with "Mode" and "Loop" are turned into "Play" on
  load. Gate and One-shot stay, either with Loop becomes Loop, since
  playing until stopped is gone.
- The keys of the Instrument tab stay half lit while a note let go
  is still heard. Esc on the keys stops everything, like Stop.
- Striking a ringing key again plays a new note beside it rather
  than stopping the old one, so a drum can be hit quickly. This
  differs from what was proposed in the issue discussion.

Tests:
- instrument + pitch-player + sound-library + node-catalog:
  477 tests, green (12 new).
- e2e 34 (melektaus-atx): ALL PASSED, 45 checks (+1). Let go after
  a loop of 0.05 s, the note played out for 0.31 s on the audio
  clock, the key half lit meanwhile.
- Counter-check: a release that does not leave the loop fails the
  2 new player tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 11:34:30 +02:00
..
Plugins belong to the project, and they load before it: the project file gained the field plugins: ["demo-plugin.js"] (default empty, no formatVersion bump), the Plugins tab's switch writes into it as an ordinary undo step (SetPluginActiveCommand) instead of into a server-wide plugins.json, and the start order is turned around - startPlugins only fetches the list of files, then editor.boot() runs and ProjectStore.load(id, prepare) hands the raw JSON through before it is deserialized, where pluginsOf(raw) reads the list and PluginManager.syncTo() activates exactly those; that is the point of the issue, because what a plugin registers has to stand there before normalizeGraph would throw it away as unknown (#126, #127), a project switch first stops what the new project does not name and then starts what it does, a file the server does not have is passed over silently, and after signing out the manager is dead so a late event cannot start anything in a torn-down session; on the server plugins.json, PluginStore::setActive, isActive, the route PUT ?r=plugins/{file} and the 403 for inactive modules are gone and GET ?r=plugins only answers {file,bytes,updatedAt}, which makes every plugin file fetchable - the consequence accepted in #117, written down in the wiki for #115 and #116; publishPlugins(root) only copies files now, the seeder switches the demo plugin on in the fixture project, and the Plugins tab carries a puzzle piece as its icon while only a plugin's own tab still goes without one (the knob and the socket are cubic curves, not arcs, which Pixi's parser draws as a spike after an L); 3 new e2e checks in module 38 and 5 new unit tests cover the project as the owner of the switch, its undo, the order, pluginsOf against crude input and an unknown file name (#119)
2026-09-20 14:24:27 +02:00