Describe a fade in and out, each along its own curve (#345)

- Sounds: Fade in, Fade out and a curve for each replace Edge fade,
  in the table, the Sound tab's header and the cut's name. A new
  section, The curve of a fade, shows all five curves.
- Development: 1852 editor checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
adminandClaude Opus 5.5 committed 2026-10-07 09:49:13 +02:00
1 parent 1fa1da14be
commit f70e4b7bc3
2 files changed
+31 -10

No files matched your search

+1 -1
@@ -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 # 1850 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1852 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
+30 -9
@@ -31,7 +31,8 @@ signature, so nothing a request claims can decide what is written.
| **Volume** | How loud this sound is by itself, 0-1. |
| **Loop** | Whether it is music: it repeats until something stops it. |
| **Start (s)**, **End (s)** | The stretch of the file the sound is, set in its [tab](#the-sound-tab). End 0 is the end of the file. |
| **Edge fade (ms)** | How long each cut edge inside the file fades in or out, 10 by default. |
| **Fade in (ms)**, **Fade out (ms)** | How long the start fades in and the end fades out when that edge lies inside the file, 5 each by default (#345). |
| **Fade in curve**, **Fade out curve** | The shape of each fade: *Linear* (the default), *Equal power*, *S-curve*, *Exponential* or *Logarithmic*. See [below](#the-curve-of-a-fade). |
The preview plays through the very same library a running game uses — same decode, same device —
so what the inspector plays is what the graph will play, cut and all.
@@ -48,11 +49,14 @@ waveform, a Sample's loop points, a Pitch.
- **Drag a handle** to move that edge. **Drag anywhere else** to span a new stretch from where you
pressed. One drag is one undo step, the two edges together. An edge cannot pass the other.
- **Whole file** in the header puts both handles back on the ends of the file.
- **Edge fade (ms)** in the header (also in the inspector) is the ramp at each edge **inside**
the file: the stretch rises from silence over it and falls back to it, so a cut through a wave
does not click. It is counted into the stretch, so the stretch stays as long as it is. An edge
on the start or the end of the file is left as it is. A fade longer than half the stretch is
shortened to half. The ramps are drawn in the wave.
- **Fade in (ms)** and **out** in the header (also in the inspector) are the ramps at the two
edges **inside** the file: the stretch rises from silence over the one and falls back to it
over the other, so a cut through a wave does not click. They are counted into the stretch, so
the stretch stays as long as it is. An edge on the start or the end of the file is left as it
is. A fade longer than half the stretch is shortened to half. The dropdown behind each field is
the **curve** of that fade. It shows the curve as a small picture, rising for the fade in and
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.
- The **wheel** zooms about the pointer, the **middle button** pans, as in the music tabs. Zoomed
@@ -64,9 +68,9 @@ waveform, a Sample's loop points, a Pitch.
at any time, and **two cuts of one file** are two assets (duplicate the asset, pick another
stretch) that share the file on the server.
**How it plays.** A cut sound is played by a name of its own, `<file>#<start>~<end>~<fade>`. The
library fetches and decodes the file once and makes the stretch from it the first time that name
plays: a copy of those samples with the ramps worked in. Length and waveform of a cut are read
**How it plays.** A cut sound is played by a name of its own,
`<file>#<start>~<end>~<fadeIn>~<fadeOut>~<curveIn>~<curveOut>`. The library fetches and decodes the file once
and makes the stretch from it the first time that name plays: a copy of those samples with the ramps worked in. Length and waveform of a cut are read
from the file itself, without a copy. Copies are made again whenever they are needed, so the
library lets the oldest go once they hold more than 64 Mi samples together — a cut dragged about
in its tab leaves no pile of copies behind. A sound over the whole file is no cut at all and plays
@@ -75,6 +79,23 @@ the file as it always did; assets saved before the tab existed are such sounds.
**Song items** keep their place and their length when their sound is cut anew: they play from the
new start, and one longer than the new stretch plays it round and round.
### The curve of a fade
A fade runs from silence to full. Its curve says how loud it is on the way, at `t` from 0 (the
silent edge) to 1 (full). A fade out runs its curve backwards, from full to silence.
| Curve | Loudness at `t` | Halfway | Sounds like |
| --- | --- | --- | --- |
| *Linear* | `t` | 0.5 | A straight ramp, the default. |
| *Equal power* | `sin(t · 90°)` | 0.71 | Keeps the power even. A fade out of one sound and a fade in of the next laid over each other stay as loud as one. |
| *S-curve* | `(1 - cos(t · 180°)) / 2` | 0.5 | Soft at both ends of the ramp, steep in the middle. |
| *Exponential* | `t²` | 0.25 | Stays quiet long near the silent edge. A fade out falls quickly and then lingers, like a sound dying away. |
| *Logarithmic* | `1 - (1 - t)²` | 0.75 | Gets loud quickly. A fade out holds long and drops at the very end. |
Each fade has a curve of its own, so a sound can, say, rise along *Linear* and die away along
*Exponential*. Sounds saved before #345 had a single *Edge fade*. It is not read anymore, so they
start with 5 ms each and *Linear* on both.
## Playing it
| Node | What it does |