diff --git a/Development.md b/Development.md index 81357ba..e814dc7 100644 --- a/Development.md +++ b/Development.md @@ -19,7 +19,7 @@ php tests/php/accounts.test.php # the API's accoun php tests/php/snapshots.test.php # the snapshot store (#231), the same way php tests/php/releases.test.php # the release store (#266), the same way php tests/php/files.test.php # uploaded files in a folder per account (#344), the same way -node tools/seed-e2e.mjs && node tools/e2e.mjs # 1890 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 1893 editor checks, screenshots in /tmp/gm-e2e-*.png GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step ./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh status # live progress, or the last run's result diff --git a/Instruments.md b/Instruments.md index 9cfd7d2..c66b352 100644 --- a/Instruments.md +++ b/Instruments.md @@ -88,6 +88,11 @@ voice 0. - **Pitch.** A Sample that follows the note is shifted by the phase vocoder of #317, so a note far from the root sounds rough, as there. A note at its root is the sound itself, played without the worklet. On a Chip a Pitch moves its frequency itself, exactly and at no cost. +- **At most 12 ways on the pitch worklet** play at once, in the whole editor or game. One more cuts + the oldest in 10 ms, a note already let go before one still held. Each runs a phase vocoder: + measured in Chrome on the Windows runner, 12 take half of the audio thread and 24 all of it. Past + that every sound dropped out until enough of them had ended, as a quick run up the keys of + sampled one-shots did. - **Sound FX node and a Mix.** The arriving sound is set in wherever the FX's Input was. A Mix in the FX therefore plays the sound twice, one source per way, as in the sound FX itself. @@ -215,14 +220,16 @@ The header says which notes the keys play (*Keys C3 to E5*), and a line under th while the keys have the focus. A held key does not repeat; letting it go, or the keys losing the focus, ends the note. A key let go stays **half lit** while its note is still heard: a one-shot playing out, a loop left, an echo. Striking it again plays a new note beside it, as a sampler does, -so a drum can be hit quickly. **Stop**, or `Esc` on the keys, ends everything the tab started. Every parameter of the +so a drum can be hit quickly. **Stop**, or `Esc` on the keys, ends everything the tab started, and +so does closing the tab or pressing Play for the game. Every parameter of the instrument has a number field in the header, starting at its default: what the keys play with, heard at once on what is playing. Those values are the tab's own and never written into the asset. ### Presets, Randomize and Mutate -Three buttons in the header make 8-bit sounds the way sfxr does (#329). Each is one undo step and -plays the note last played at once (C4 before any), for up to 2 s. +Three buttons in the header make 8-bit sounds the way sfxr does (#329). Each is one undo step. +Randomize and Mutate play the note last played at once (C4 before any), for up to 2 s. A preset +plays nothing: try it on the keys. With Audition on it is heard like any other change. - **Preset** opens a menu in two parts. Either kind puts a new graph in place of the instrument's; groups and notes on the canvas stay. diff --git a/Patterns.md b/Patterns.md index 807c91a..0eb9029 100644 --- a/Patterns.md +++ b/Patterns.md @@ -138,8 +138,8 @@ next window on, without starting over: a note drawn ahead of the playhead in thi behind it in the next. A new loop or tempo counts from what is planned. Playing goes on while another tab is open, so an instrument can be changed while its pattern plays. -It stops when another pattern is shown in the tab, when the pattern is gone and when a project is -opened. +It stops when another pattern is shown in the tab, when its tab is closed (a key of the roll too), +when the pattern is gone, when Play starts the game and when a project is opened. Measured (2026-10-06, e2e 64 on the CI's Windows machine): bar 1 of a pattern at 120 BPM, its notes at ticks 720, 960, 1440 and 1680 were planned exactly 0, 0.25, 0.75 and 1 s apart on the audio diff --git a/Songs.md b/Songs.md index 676d00d..1b9e8e0 100644 --- a/Songs.md +++ b/Songs.md @@ -181,7 +181,8 @@ next window on, without starting over; a track's volume, pan, mute and solo at o The editor plays one piece at a time: playing a pattern stops the song, and playing the song stops a pattern. Playing goes on while another tab is open; it stops when another song is shown in the -tab, when the song is gone and when a project is opened. +tab, when its tab is closed, when the song is gone, when Play starts the game and when a project is +opened. Measured (2026-10-06, e2e 65 on the CI's Windows machine): a sound clip on the first track and a pattern at bar 3 on the third, at 120 BPM, were planned 4 s apart, the pattern's notes 1 s apart, diff --git a/Sounds.md b/Sounds.md index b027434..5d1c889 100644 --- a/Sounds.md +++ b/Sounds.md @@ -64,7 +64,8 @@ waveform, a Sample's loop points, a Pitch. falling for the fade out; its tooltip names it. The ramps are drawn in the wave, each in its curve. - **Play** (or Space) plays the stretch once, at the asset's volume, with a playhead. It ends - whatever pattern or song the music tabs were playing, as they end each other. + whatever pattern or song the music tabs were playing, as they end each other. Closing the tab + and starting the game end it. - The **wheel** zooms about the pointer, the **middle button** pans, as in the music tabs. Zoomed in far enough, the samples themselves are drawn as a line. - A stereo file shows **one** wave, the loudest of its channels; it plays in stereo. @@ -459,7 +460,16 @@ change ends. The end is timed on the clock of the sound, so a paused run holds a - **Cost**: a Delay is a handful of Web Audio's own nodes per voice, no worklet. In e2e 34 headless Chrome on the CI's Windows machine rendered 64 stereo voices with a ping-pong Delay for 2 s in about 0.3 s, so about **400 of them play at once** (2026-10-06). There is no limit on how many - voices play, also now that they live longer. + voices play, also now that they live longer. Only the ways on the pitch worklet are held to 12, + see [Instruments](Instruments#how-a-note-is-made). +- **What has ended is let go.** A voice without echoes leaves its bus as soon as its sound and what + its stages hold back are through, one with echoes once they have faded. A way or stage on the + worklet closes its port when it ends or is stopped. Before that a port that was listened to was + never collected, and through it neither was its voice: every node of it stayed on its bus and + was worked on in every block. Measured (2026-10-08, a copy of a project, a song of 4 tracks + played for 12 s and stopped, Chrome on stein2): 740 nodes were left behind each time, 4469 after + six times, and the load of the audio thread at rest grew from 1 % to 6 %. Since then 7 are left, + the master and one bus, however often it is played. ### Filter @@ -670,7 +680,8 @@ stays. **Listening in the tab.** The header picks one of the project's sounds and plays it through the graph as it stands — the same library as a running game, so it sounds the way the game will. -`Stop` there ends only what the tab started. Play is offered only while the graph compiles. +`Stop` there ends only what the tab started, as closing the tab and starting the game do. Play is +offered only while the graph compiles. Every parameter has a number field in the header, starting at its default: what Play hands in. Moving a field while the tab plays is heard at once on that sound. Those values are the tab's own and never written into the asset.