Zoomed out, the wave left room above and below it, but the bright file,
the picked clip and its handles still took the whole height. And a click
in the wave beside the picked clip kept it picked, so only the strip
could take it back to the sound.
- fileReach in waveView.ts is how far up and down the file reaches:
full scale and its inset, never past the area. At level 1 it is the
whole height, zoomed in too.
- The bright file, the shade outside the clip and the two handles are
drawn within that reach.
- A click over the wave beside the picked clip picks the sound. Inside
the clip or on a handle nothing changes, and a drag still spans the
clip anew.
Tests:
- Unit wave-view: 11 green (1 new), a counter-check red
- e2e 34 (melektaus-atx): ALL PASSED, 91 checks (1 new)
- Gate (melektaus-atx): CHECK EXIT 0, 271 files, 4195 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A sound could only be cut to one stretch, set on the asset itself. To
play two parts of one file, the file had to be imported twice. Now a
sound is always the whole file, and its clips are the stretches of it,
each with a name and a cut of its own.
- A clip is { id, name, props } on SoundAsset.clips. Its id shares the
generator with asset ids, so a sound field holds a sound or a clip,
as a texture field holds a texture or a frame.
- props are the cut: start, end, the fades and their curves, reverse.
Volume, loop, sound FX and bus stay on the sound for all its clips.
The cut rows left the sound's schema for CLIP_ROWS.
- findSound resolves either id. Play sound, the Sample of an
instrument, a Reverb impulse, song items, the scheduler and the test
sound of the Sound FX tab all go through it.
- Every sound field offers each sound followed by its clips, "Kick",
"Kick / Clip 1". A clip that is gone reads as "<id>?".
- The Sound tab has a strip under the ruler with the clips as bands.
A drag there makes a clip, a click picks one, beside the bands the
sound. Only the picked clip has handles. Reverse, fades and curves
in the header work on it and are greyed out without one.
- Whole file is gone from the header, as the user asked.
- Picking a clip is a selection of its own, like a frame. The
inspector shows its name, its cut rows and Delete clip. Delete
takes it away without asking, as with a frame. Ctrl+Z brings it
back.
- Copies get fresh clip ids: Duplicate, Embed a copy, a song
duplicated with its takes, and the copy a split or paste makes of
an embedded take. An item on a clip plays the same clip of its copy.
- A double-click on a song item playing a clip opens its sound with
the clip picked. The Sound row of an item on an embedded take
offers the take and its clips, which no list shows.
- A new take stays the whole sound. Clips are made by hand, as the
user decided.
- No migration in the code, as the user decided. The one project
with cut sounds was changed over by hand.
Deviation from the issue: deleting a used clip does not warn. A frame
does not warn either, and the issue had promised "like a frame".
Tests:
- Unit sound-clips (new): 11 green, 7 counter-checks each red
- Unit sounds, embedded: adjusted to clips, green
- e2e 34 (melektaus-atx): ALL PASSED, 90 checks (3 new, 12 rewritten)
- Counter-check in the browser: clips left out of the sound fields,
the picker check fails
- Gate (melektaus-atx): CHECK EXIT 0, 271 files, 4194 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Sound tab always drew the wave at the full height of the tab. Quiet
stretches were hard to see, and there was no room above a loud wave.
- A level scale in dB stands left of the wave, a mark every 6 dB down
from 0, as long as a mark lies inside the area and at least 14 px
from the middle.
- The wheel over the scale zooms the height, from 0.25x to 16x. Over
the wave it zooms the time as before.
- What is louder than the area stops at its edge. The fade ramps grow
with the wave.
- Fit puts the height back to 1x. The tab keeps the height with its
view when another tab is shown.
- The rules live in waveView.ts (zoomLevel, levelMarks), the hooks
give the height, the scale and the top of a full-scale wave.
Tests:
- Unit wave-view: 10 green (2 new), 2 counter-checks each red
- e2e 34 (melektaus-atx): ALL PASSED, 87 checks (1 new)
- Gate (melektaus-atx): CHECK EXIT 0, 270 files, 4183 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A sound asset now opens in a tab that shows its file as a waveform.
Two handles set where the sound starts and ends in the file, and that
stretch is the sample: Play sound, a song item and an instrument's
Sample all play it and nothing else. The file itself is never changed.
- The asset has three new rows: Start (s), End (s) and Edge fade (ms).
End 0 is the end of the file, the fade is 10 ms by default. Older
assets have no values and play the whole file as before.
- Every way of playing asks playedSoundOf() for a name instead of the
file: the file, or <file>#<start>~<end>~<fade> for a cut.
- SoundLibrary makes the cut from the decoded file the first time that
name plays and ramps each edge inside the file over the fade. Length
and peaks of a cut are read from the file without a copy.
- Cut buffers can be made again at any time, so the library lets the
oldest go past 64 Mi samples. A voice holds its buffers itself.
- The tab draws min/max per pixel from 256-sample block peaks, and the
samples as a line when zoomed in far. Wheel zooms, the middle button
pans, as in the music tabs. Wave, cut and ruler sit under a mask,
so a handle panned out of view does not draw over the panels beside.
- Dragging a handle moves that edge, dragging elsewhere spans a new
stretch. One drag is one undo step for both edges. Whole file puts
the handles back, Play or Space plays the stretch with a playhead.
- The inspector preview and the Sound FX preview play the cut too, and
the song lanes draw and repeat it.
Tests:
- Unit: sounds 20, wave-view 8 (new), sound-library 68, plus 258 in
the touched areas (instrument, song, pattern, inspector, tabs)
- e2e 34 on melektaus-atx: ALL PASSED, 57 checks (7 new)
- Gate on melektaus-atx: CHECK EXIT 0, 253 files, 3936 tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>