b50c7dbc35421cc340c04cd6099eda64bafc2d49
25
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b50c7dbc35 |
Let a song track automate parameters of its sounds and FX (#337)
Stage 3 of #337. Lanes moved volume and pan only. Now a lane can steer a parameter of anything on its track, and a voice already planned or still waiting for its file follows it too. - A lane may aim at param:<name>. A parameter has no range of its own, so the lane keeps min and max. A parameter lane stays without points, so its range is not lost. Remove lane takes it away. - It reaches the track FX, the FX of an item, the instrument of a note with its own FX, and the FX of a clip. When several have the name, all of them change, as with Set sound FX parameters. - The scheduler hands the lane value to a note or clip at its start. Values a voice only reads at its start act from the next note. - While a voice sounds, the knobs of buses and voices of the track follow the lane on the audio clock, read every 10 ms, because a knob is not always the parameter itself (trackParams.ts). - A voice waiting for its file takes the marks when it starts. - When a lane is removed, the parameter goes back to its default. An edit while playing does not reset a parameter a lane rules. - This holds in the song tab, for Play song, in compositions and in the bake. - Song tab: Add parameter lane in the track head menu opens a dialog for parameter and range (ParamLaneDialog.ts). The lane head menu has Range and Remove lane. - Inspector: while a lane rules a value, a hint at the track names the lanes and says the fields act once the lane is gone. Known limit: a knob that depends on two automated parameters reckons each lane with the last value of the other, so it may lag one window. Tests: - automation-params.test.ts (9, new), 3 new in sound-library and 3 in song-lanes. Affected files 407/407. - 17 counter checks, all compile, all red. - e2e 65 on melektaus-atx: ALL PASSED, 67 checks. 65h3 is new: a clip with FX parameter cut starts at the lane value and its knob stays within 0.04 dB of the lane. It goes red when automateBus does not pass parameters on. - Gate on melektaus-atx: CHECK EXIT 0, 330 files, 5080 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
bd99f9e79d |
Let automation lanes of a song track be drawn in the song tab (#337)
Stage 2 of #337. The lanes of stage 1 played, but nobody could make one. Now a track folds out a lane for volume and one for pan, and points are set, dragged and eased right on the timeline. - A lane is a row of its own, as high as a track, below its track. The view functions stay row based, so zoom, fit, item drags and the composition (which shares them) are unchanged. - itemAt and itemsWithin take a map of track id to row. - A triangle in the track head folds the lanes out. The head menu shows or hides each lane. A lane with points is open by itself. - Which lanes are open belongs to the view of the tab and is saved with it. It is not part of the song and makes no undo step. - A click sets a point on the grid, Alt or Shift on the exact tick. Press and drag sets one and drags it in a single undo step. - A dragged point stops at its neighbour. Two points on one tick make a jump. Double click or Delete removes a point. - The value shows next to a dragged point and as a tooltip. - Right click on a point opens "Ease to next point" with the same choice as animation keys, curve assets included. - The lane head shows the value at the playhead. Its menu clears or hides the lane. - While a lane rules a value, the fader shows it in the lane colour and cannot be dragged (decision 4). A hint says why. - Geometry in laneView.ts, edit rules in laneEdit.ts, the easing menu in easingMenu.ts. New test hooks automationAt, automationHeadAt and automation under __gm.song. Open: the Volume (dB) field of a track in the inspector can still be changed while a lane rules it. It has no effect while playing. Tests: - song-lanes.test.ts (12, new) and song-edit adapted: 27/27. Editor tests of song and composition 62/62. - 9 counter checks, all compile, all red. - e2e 65 on melektaus-atx: ALL PASSED, 66 checks. 65g2 is new with 6 checks. It goes red when a set point is not taken on release. - Gate on melektaus-atx: CHECK EXIT 0, 329 files, 5065 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
406839baea |
Drag clips of videos and sounds straight onto a track (#425)
A clip of a video could not be laid on a composition track at all, and neither could a clip of a sound, although #418 and the wiki said so. The only place a drag starts is the asset panel, and it listed assets, not clips. The texture label of an item playing a video clip was dead too, because the reference lookup did not know video clips. - The asset panel gives a sound or video with clips a chevron of its own. It unfolds one row per clip and starts closed. - A clip row drags like an asset. One click shows the clip in the inspector without leaving the tab (`EditorState.glance`). A double click opens its sound or video with the clip picked. - A video clip dropped on a composition track becomes an item as long as the clip. It wears the sprite of its whole video, so a composition keeps one sprite per video, and the clip is a texture override on the object. Sprite, item and override are one undo step (`droppedPicture`). - A sound clip becomes an audio item as long as the clip. The song tab takes sound clips on the same way, through `findSound`. - `referencedTarget` lets a reference label link to the clip itself. One click pings the clip row, a double click opens the asset with the clip picked. The Plays row of an audio item reads "Sound / Clip". - `clipOwner` in `sound.ts` finds the sound or video a clip id belongs to. `activateAssetOrClip` uses it for the double clicks. Found on the way: the Blip of the e2e seed is only 0.25 s long, so a clip of 0.2 to 0.7 s on it is cut to one frame. 69s takes the Drone (0.75 s) instead. Tests: - tsc, eslint, Prettier clean - Unit on stein2 (composition, references, sound, video, editor): 94 files, 1238 tests green - e2e 69 on melektaus-atx: ALL PASSED, 25 checks, 2 of them new (69s) - Gate on melektaus-atx with the fix for 68k on top: CHECK EXIT 0, 313 files, 4841 tests - Counter checks, all red: no clip rows in e2e 69 (no drag starts), no clip override in the unit test, the link aimed at the asset instead of the clip - Not covered by its own e2e check: sound clips on the song tab Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0701fe3856 |
Share the parts the sound devices and timelines repeated (#85)
Round 12 of the clean-up. Duplicate code had grown from 33 clones (249 lines) after round 11 to 140 clones (1263 lines), almost all of it in the panels and faces of the sound FX devices (#379 to #401). It is down to 57 clones (416 lines) now, and src is 816 lines shorter. - deviceParts.ts holds what the device panels built by hand: the head, rows of knobs, the screen style and the row layout for groups of knobs. Twelve panels use it. panel.knobs stays because the debug hooks read it. - DeviceFace is the base of the twelve faces. It finds the node and does wired, preview, commit, set, hide, reload and audition. compressorWired lives there as paramWired. - TextPool replaces ten copies of "make texts as needed, hide the rest" in the wave and video tabs, the rulers, the piano roll and the song and composition timelines. clipStrip.ts is the clip label strip the wave and video tabs share. - core/util/bytes.ts has the concat that ogg, matroska and avcColour each wrote out. - Dead code is gone: clear on the video players (never called since #402), posterFileOf and videoTimeAt (only tests called them) and easeOut (the same as glide(t, 3)). Values only used in their own file lose their export. - Comments over 125 columns are wrapped, and comments that told the history ("as before", "used to") say what is, in src and in the e2e modules. - Left alone on purpose: AnimationEditor and CompositionEditor share only the play button, and the curve panels are built differently. - Chip now places its boxes through put, which rounds. They were whole numbers already. The three row layouts are byte-identical before and after. - README lists the video and composition assets and the Videos and Compositions pages. Tests: - Gate (melektaus-atx): CHECK EXIT 0, 313 files, 4835 tests. - e2e 25, 34, 64, 65, 66, 69 (melektaus-atx): ALL PASSED, 330 checks. - TextPool without keeping its texts and framesToRoom without making room both go red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5df2173559 |
Show Delete in red in the track and item menus of both timelines
A composition clip had a red button in the inspector that did the same as its menu entry. Deleting a track looked like any other entry in the menu, although it takes the track with everything on it. - The inspector of a clip drops "Remove clip(s)". Right-click and the Delete key still remove it. - "Delete track" is red in the Composition and Song tabs, behind a separator like "Remove item" in the other menus. - "Delete" on a Song item is red, too. Tests: - Gate on melektaus-atx: tsc, eslint and Prettier clean, 305 files, 4722 tests passed. - No check clicks the inspector button or counts the track menu, so no e2e module ran. The red entries were not looked at in a picture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
597367c804 |
Keep a transition's pace through new steps and pans (#309)
A wheel step in the middle of a transition restarted the ease-out curve at full speed, so a run of quick steps kicked at each one. A pan called finish() first and made the zoom jump to its target. Both made the zoom and the gliding lists feel jerky. - A new step starts from the speed the view already has and then eases out. Quick steps in one direction move in one stroke. A step the other way still starts from rest. - A pan takes the transition along. The zoom goes on while dragging and lands where it was heading, moved by the pan. This covers all eight pan places: scene and container, graph, plugin board, texture and pixel art, timeline, pattern, song and sound. - finish() is gone, it has no callers left. Dragging the scrollbar, a jump to a row, another document or a new view size still end the transition as before. Found: on a second step the old curve jumped to 2.47 times the speed the view had just before. Tests: - npm run check on stein2: 299 files, 4598 tests (5 new) - e2e 46 on stein2: ALL PASSED, 24 checks (1 new). A pan by 40/30 px during a 1000 ms zoom step leaves it moving (2.33 on the way from 2 to 3), it lands on 3 with the world point moved by the pan. - Counter-checks: with the pace reset to 3 the new unit test fails with 2.47 instead of at most 1.1. Without carry the pan test fails. - melektaus-atx went offline mid-run, so both ran on stein2. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
23922ee4a2 |
Show the zoom of the music tabs and the EQ as a transition (#377)
The zoom transition of #309 left out the Pattern, Song and Sound tabs
and the Parametric EQ's curve. There a wheel step or Fit still jumped,
whatever "Zoom (ms)" in the general settings said.
- axisTween wraps ViewTween for a single axis. The music tabs zoom
their time across and their rows, tracks or height down apart, so
each keeps one tween per axis and either goes its own way.
- Fit by its button is shown as a transition too, as in the other
tabs. The fit on opening a document still jumps.
- A middle-button pan first lands a transition under way, and saving
a document's view lands it on the step it was heading for.
- The EQ's range is saved on the node at once. While the zoom is on
its way the curve draws a range of its own and writes nothing.
Its dB lines are those of the new range, sliding to their place,
so no line shows a crooked number.
Found on the way, not part of #377:
- CI task 611 for
|
||
|
|
2764919bb8 |
Stream long sounds from an Opus copy instead of decoding them (#349)
A sound was decoded whole as soon as the project opened, in the editor and in a released game: five minutes of stereo held some 115 MB for as long as the page was open. A sound with Stream on now plays from a copy as Opus in Ogg, fetched a piece at a time and decoded a few seconds ahead by WebCodecs, so a game holds a few megabytes for it. - The Stream switch is a row of the sound, off by default. The Sound tab suggests it from a minute on and says how far the copy has got. - StreamKeeper makes the copies in the browser, a moment after the last change, one at a time: the sound's own and one per clip of its cut, fades and Reverse baked in. A copy that is no longer wanted is taken off and deleted once the project is saved without it. - streamTable says which played names stream from which copy. A clip without a fitting copy, a Sample and a Reverb impulse stay decoded. A sound with Stream on is never decoded ahead. - The page fetches by Range and takes the whole file from a server that ignores it, as the CI's PHP server does. It keeps the bytes and the first two seconds decoded, the rest goes four seconds ahead. - A jump decodes 32 packets before the place first. Measured in Chrome, what follows is then the same to the bit as decoding from the start. With 4 packets it was 0.06 off. - The stream-player on the FX worklet reads the samples at the rate of the context along a Catmull-Rom curve. What comes late is silent and skipped once it is there, so a clip keeps its beat. - The opening stretch goes with the player as it is made. Sent by message it came a few milliseconds late, and 557 samples of the attack were lost. - Pitch on a streamed sound is a shifter after the player, as on a bus: the length stays and it is heard 42.7 ms late. - Bakes of patterns and songs (#340) always stream now. - The song timeline draws a streamed sound from its copy decoded at 8 kHz, keeping only the peaks. Tests: - Gate: CHECK EXIT 0, 280 files, 4312 tests (31 new: ogg +3, stream-queue 6, streams 11, streaming 6, sound-library +5). - e2e 34: ALL PASSED, 106 checks (7 new). Five minutes of mono, 4.8 MB as WAV, 3.6 MB as its copy: streamed the renderer grows by 5.8 MB, decoded by 69.6 MB. Offline at 48 kHz, start, loop seam and a reversed clip are the copy decoded whole to the sample (0). - Counter-checks red as they should be: no pre-roll, no catch-up of late samples at the end, no opening stretch, a streamed sound decoded ahead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
25084f8576 |
Refactoring round 10: split SoundLibrary, fold sound duplicates (#85)
Refactoring round 10 covers everything since round 9 ( |
||
|
|
d0b76ec355 |
Fit a song both ways and zoom its time in further (#362)
Fit in the Song tab only set the time, from the very left edge, and kept the height the tracks had. The time also stopped zooming at the bound of the Pattern tab, too soon to lay a take down closely. - fitSong in songView.ts frames the song with 9 % of the lanes free on every side. The tracks share out the height in between, held to 28 to 320 px. A song opened without a kept view fits the same way. - The time zooms in to 8 px a tick, eight times the bound of the Pattern tab. zoomTime takes the bound as a parameter, so the Pattern tab keeps its own. Tests: - Unit song-edit: 15 green (1 new), the counter-check without the margin is red. - e2e 65: ALL PASSED, 56 checks (1 new). The new check presses Fit after the tracks are added and finds room around bar and tracks. Adding a track presses Fit first now: a new song opens with its one track 320 px tall, so the track added below it lay off the edge. - Gate: 272 files, 4213 tests green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
490fcba88f |
Meter each track and the song, and limit the output at -1 dBFS (#359)
A song could clip at the output without anyone noticing: a track and a sound item at +12 dB each add up to +24 dB. The Song tab now shows how loud each track and the whole song are, and a fixed limiter behind the master keeps every sample under -1 dBFS in the editor and in the game. - Each track head has a stereo meter up its right edge. The head is 190 px wide instead of 176. - Out sits in the corner above the heads, with the loudest peak since Play in dB. In the tab header it made the row too wide for a 1280 px window, and the inspector lost its fields. - The meters read AnalyserNodes beside the buses, one per side after a channel splitter, so a peak panned hard is not halved. They are tapped only while the song plays and its tab is shown. - A clip lamp lights past 0 dBFS and stays through Stop. The next Play or a click on the meter puts it out. - The meter of a track that mute or solo keeps from being heard is grey. - Music always plays through a bus of its own, with or without a sound FX. That bus is what Out measures. - The limiter is the one from #326 and needs the FX worklet. Until that is loaded the master goes straight out. - It is 5 ms late. latency() counts that in, so the playhead and the alignment of a recorded take follow it. - Unit tests build SoundLibrary without the limiter, as their wiring checks follow every node of a voice. - Out shows "-inf" while nothing was loud. The UI font has no infinity sign, which the font test found. Tests: - Unit meter-view 8 new, sound-library 112 (2 new), 3 counter-tests each red - e2e 65 (melektaus-atx): ALL PASSED, 55 checks (3 new). Out wrote +16.6 dB, behind the limiter the loudest sample was 0.8913 - Gate (melektaus-atx): 272 files, 4209 tests, one red in the font test. Fixed after it, then the font and meter tests ran green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
42a3759d9d |
Cut a sound into named clips, as a texture into frames (#357)
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>
|
||
|
|
668682c4ff |
Give a song, a track or an item a sound FX of its own (#355)
A sound FX for one place in a song had to be a project asset, which then stood in every picker. Now every pick of a sound FX in a song can make one the song keeps for that place alone, on top of the embedded assets of the first two parts. - Create sound FX sits at the end of the Sound FX row of the song, a track and an item, and of the menu of a track's FX button. It makes "Sound FX 1", 2, … per song with the Input wired to the Output, picks it and opens it. That is one undo step. - Embed a copy, while the place names a project FX, gives the place a copy under the same name. - While the place names its own, the menu shows it with the mark and offers Edit sound FX and Make project asset. - Picking anything else lets it go in the same undo step. For a track or an item `settleEmbedded` did that already. For the song's own row `AssetPropertyCommand` now settles the song after `fx`. - The mark `•` moved to the core. `assetRefLabel` puts it in front of an embedded asset, so the inspector rows show it like the timeline. - `FieldHandlers.moreChoices` lets a caller end a reference menu with entries of its own. `embeddedPatternName` is `embeddedName` with a base now. Tests: - Unit own-fx (new): 6 green, 6 counter-checks each red - Unit embedded and 80 neighbouring files: 1434 green - e2e 65 (melektaus-atx): ALL PASSED, 51 checks (2 new) - Gate (melektaus-atx): CHECK EXIT 0, 270 files, 4178 tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
49669017b1 |
Make a pattern right in a song with a right-click (#355)
A pattern for one song had to be made in the Assets panel first and dragged in, and then stood in every picker of the project. Now a right-click on an empty spot of a track makes one the song keeps to itself, on top of the embedded assets of the first part. - Create pattern lays an item from the grid line before the spot, a bar long, and opens the pattern in its tab. Pattern, item and name are one undo step. The name is "Pattern 1", 2, … per song. - It plays the instrument of the track's pattern item that starts last before the spot, else of the first one after it. An item's own pick counts before its pattern's. - An embedded pattern runs on the song's clock. It takes the tempo and the meter of the song, and a change on the song moves it along in the same undo step (`AssetPropertyCommand`). - Its rows Tempo, Beats per bar, Beat and Bus are hidden, as the song decides them. Length, grid, instrument and sound FX stay. - A copy that comes to a song (Embed a copy, a paste from another song) takes that song's clock. Made a project asset, it keeps the values it had. - `CreateAssetCommand` takes an owner. `embeddedCopy` takes the song now, not its id. - The cleanup of e2e 65 also takes what the song keeps. Tests: - Unit embedded: 18 green (5 new), 6 counter-checks each red - Unit take, song, pattern and the asset commands: green - e2e 65 (melektaus-atx): ALL PASSED, 49 checks (2 new) - Gate (melektaus-atx): CHECK EXIT 0, 269 files, 4172 tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
23cb34f781 |
Keep a recorded take inside its song (#355)
A take used to land in the Assets panel as "Song – Take N", next to every other sound of the project. Now a song can keep a sound, a pattern or a sound FX to itself: an ordinary asset whose new field `owner` names the song. Everything that finds an asset by its id finds it, so playing, the tabs and the game need no change. Only the places that list assets leave it out. - `core/music/embedded.ts` holds the rules: which types can be embedded, `listedAssets`, the title "Song › Take 1", and the rows an embedded sound hides (Loop, Bus). - One user per embedded asset. `SetSongCommand` settles the song after every edit: a place naming an asset an earlier place claimed, or one of another song, gets a copy, and what nothing names any more goes in the same undo step. The outcome is worked out once, so a redo brings back the same copies. - A split, Ctrl+D and a paste get that for free. The clipboard keeps the embedded assets of the copied items, so a paste after a delete brings the take back. - Deleting a song deletes what it keeps. Duplicating it copies that and points the copy at the copies. A duplicate of an embedded asset is a project asset. - The item menu has Open, Make project asset and Embed a copy. - An embedded item carries a bullet in front of its name. The first pick was a diamond, which the gate's font test refused: the UI font has no glyph for it. - A take is "Take 1", 2, … numbered per song. With the song gone while it uploads, it becomes a project sound under a free name. - Left out of: the Assets panel, every asset picker, the sound FX menu of a track, the test sound of the Sound FX tab and the naming of new assets. Delete on an embedded asset only says where it lives. A ping lights up its song. - Loading drops an `owner` whose song is gone, the asset stays as a project asset. No migration: older projects have no owner. Tests: - Unit embedded (new): 13 green, 6 counter-checks each red - Unit take, song, song-edit, asset-fx, asset-ref, serialize and neighbours: 116 green - e2e 65 (melektaus-atx): ALL PASSED, 47 checks (1 new) - Counter-check e2e 65 (asset panel unfiltered): exactly that check red - Gate (melektaus-atx): CHECK EXIT 0, 269 files, 4167 tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a295d233ed |
Give sounds, instruments, patterns and songs a sound FX (#352)
A sound FX could only be picked where something was played: on a Play
node, a track or an item of a song. A sound that should always sound
through the same effect needed that pick everywhere it was used. Now
the asset says it once, and every place that plays it follows.
- New row Sound FX on a sound, an instrument, a pattern and a song,
right before Bus. A sound goes through it on every voice, an
instrument on every note after its graph, a pattern on all its
notes together and a song on its output.
- The fx input of Play sound, Play note, Play pattern and Play song
and the Sound FX of a song item now read "From the asset" while
empty. None is a pick of its own, stored as `#none` like `#master`.
A pick replaces the FX of the asset, it does not come on top.
- A pattern item's Instrument reads "From the asset" instead of None.
The meaning is unchanged.
- A double-click on a sound item opens the sound, as one on a pattern
item opens the pattern.
- The tabs play through the FX of their asset. The Pattern and Song
tab put it on a bus of their own between the output and the bus of
the asset. The keys of the Pattern tab play there too.
- Notes of a pattern or song go through the FX of their instrument.
Its chain is loaded with the other needs of the sequence.
Decided without asking:
- Old items and Play nodes with an empty fx now mean "From the
asset". No asset has an FX yet, so nothing sounds different.
- The label is "From the asset" as on Loop and Bus, not "From asset".
- A sound used as a Sample, as the impulse of a Reverb or as the test
sound of the Sound FX tab plays without its own FX.
Findings:
- In e2e, `__gm.inspectorField('Sound FX')` and `('Instrument')` find
the group of the Assets panel first. The check asks for the last
match.
Tests:
- Unit asset-fx (new): 8 green. Six counter-checks each turned red.
- Field lists of sound, pattern and song: Sound FX added.
- e2e 65 (melektaus-atx): ALL PASSED, 46 checks (3 new). Counter-check
without the FX bus of the tab: that check red.
- Gate (melektaus-atx): CHECK EXIT 0, 268 files, 4142 tests.
- Not checked: how it sounds, the Sound, Instrument and Pattern tab
in the browser.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
||
|
|
d505f6ed27 |
Show what the song plays around a pattern as ghost notes (#339)
A bass line is written against the chords it goes with. Until now the piano roll showed only the pattern itself, so writing a part to fit the rest of a song meant switching between the Pattern and the Song tab. - A double-click on a pattern item remembers song, item and the round clicked into for that pattern. The place lives in the session, not in the project, and goes by the item's id, so moving the item moves the ghost notes along. - Opened from the Assets panel, the pattern shows the item of the last double-click. Without one, a pattern that lies in exactly one item of all the songs shows that item's first round. - Ghost notes are the pattern items of the other tracks all along the song, and on the own track the items before and after and the other rounds of the item. The round edited itself does not count. Sound items have no notes. - A ghost note sits on the row it sounds with: its own transpose, less the transpose of the item the pattern was opened from. - The roll draws them grey, without an edge, under the notes. Resting on one names its track and its pattern. - The header has a Ghosts switch, on by default, and names where they come from, e.g. "Tune · Bass · bar 5". - The time axis pans back to the start of the song, with bar and grid lines before the pattern. Fit still frames only the pattern. - A click or a paste outside the pattern no longer lands. Before, only the time left of bar 1 was closed, notes could still be drawn past the end, where they are kept but never played. - The rounds of a pattern item are now worked out in one place, itemNotes() in song.ts, which songSequence() and the ghost notes share. Tests: - Unit ghosts (new): 5 green. Counter-check with the round edited not left out and the own transpose not taken off: 2 red. - Unit piano-roll: 1 new (pan back to the song, lines before bar 1). Counter-check without the song's start: red. - e2e 65 (melektaus-atx): ALL PASSED - 38 checks (3 new). The first run was red on the tooltip check: the ghost note it rested on lay a fifth up, outside the rows Fit frames. The test now uses a tone. - e2e 64 (melektaus-atx): ALL PASSED - 30 checks. - Gate (melektaus-atx): CHECK EXIT 0, 260 files, 4027 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
b519cd192f |
Send a track, a pattern item or a whole song through a sound FX (#346)
A sound FX could only be put on a single sound. Now a track, a pattern item, a Play pattern and a Play song send everything they play through one chain of it, as an insert in a DAW. A Play note gets one of its own. - Track: an FX box in the head next to M and S opens a menu of the project's sound FX, and the track's inspector has the row too. Order: items, track FX, volume, pan. - Pattern item: Sound FX in its inspector. Its notes play on a bus of their own into the track's bus. - Play pattern and Play song take fx and fx params. The chain sits on the master of the playing, after the tracks and before the level and the fades. Set sound FX parameters reaches it by the playback. - Play note takes fx and fx params next to the instrument's params. The FX parameters go by "fx:" so the two sets stay apart. Set sound FX parameters on a note changes a name both have in both. - A Pitch on a bus is a new PitchShifter: the phase vocoder of the PitchPlayer, fed while it plays. It cannot look ahead and is exactly one frame late at every pitch, 2048 samples. - That latency is made up. The other way of a Mix is held back by a delay of the same length. Every note and clip starts as much earlier as the buses it passes are late. The scheduler plans that much further ahead, and the first note waits that much after Play. - The Song tab waits for the chains before it plays and lets its buses go a moment after Stop. A playing in a game lets them go after its echoes and what the shifters still hold. - songBuses moved to its own file. Kept in song.ts it pulled the FX compiler into the node registry through an import cycle. Decisions of the user: one chain for the whole (1a), FX everywhere asked for (2a), Set sound FX parameters on playbacks (3a), and a pitch shifter of its own with exact latency compensation for a Pitch on a bus. Tests: - Unit pitch-shifter (new): 11 green. At 0 semitones the output is the input 2048 samples later, off by at most 1.2e-7. - Unit sound-library: 84 green, 8 new. Counter-checks (no early start, no Mix delay, chain made every time, tune misses the master) each turned their test red. - Unit bus-fx (new): 6 green, 4 counter-checks red. Scheduler ahead: 1 new, its counter-check red. - e2e 65 (melektaus-atx): ALL PASSED, 35 checks, 4 new, first run. Chrome at 44.1 kHz: the bus was 0.046440 s late, the note started exactly that much early. Offline the shifter moved 1 kHz to 2000 Hz and passed a click 2048 samples later. - Gate (melektaus-atx): CHECK EXIT 0, 259 files, 4021 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
f1f4a57589 |
Cut a sound to a stretch of its file in its own Sound tab (#343)
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> |
||
|
|
2fdf97f7de |
Record a take from the microphone in the Song tab (#342)
A song could only be filled with sounds that were made somewhere else. Record plays the song from the cursor and takes the input meanwhile, so a part played along lands on the bar it was played to. - An audio worklet takes the input's samples on the clock the song plays on. Each run carries the frame it was taken at, so the take is cut where the song was heard to start. The output's and the input's latency are taken off, as far as the browser reports them. - The take goes up as mono 16-bit WAV. Sound, a new track "Recording" under the track clicked last and the item at the cursor are one undo step. The sound is named "Song – Take 1", 2, 3 and so on. - While recording the take grows red with its waveform on its track, and a meter beside the input dropdown shows the level. The lanes take no edits then, only a middle-drag pans. - The loop is not used while recording. The song plays once through and on past its end until Stop, Play or Space keep the take. Esc throws it away and nothing goes up. - Echo cancelling, noise suppression and auto gain are off, nothing is played back. The input picked is kept in localStorage. - A take stops by itself at the size a sound may have. A failed upload offers Retry, Download WAV and Discard. - The API takes sounds up to 256 MB and bodies of the same size. nginx and PHP were raised to match outside the repo (body 256m, upload and post 256M, memory_limit 512M). - The pure rules (cut, cap, WAV header, name, track) live in core/music/take.ts. The scheduler tells where it started on the audio clock. - The e2e browser gets chromium's fake microphone and skips the permission prompt. Each run leaves its take in the sound store. Found on the way: - The header was too full with the new widgets and cut the track and item count on the right. Input dropdown and meter are narrower now. Tests: - Unit take.test.ts: 7 new, svg-icons adjusted to 8 toolbar icons - e2e 65 (melektaus-atx): ALL PASSED – 31 checks (+4) - Gate (melektaus-atx): CHECK EXIT 0, 252 files, 3923 tests - Probe on stein2: a 3 s take of the test tone, peak 32767, 285100 bytes, waveform seen in the screenshot Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5fde3e975e |
Reset a track slider with a double-click in the Song tab
The heads of the Song tab had four rough spots. Panned down, the first track had no line above it. The M and S letters sat high in their buttons. A volume or pan slider could only be dragged back to the middle by eye. Muting a track paled its volume slider. - The first track draws a border along its top, in the lanes and in its head, like the one below every track. - M and S sit in the middle of their buttons. A label of the heads can now carry a height and is centred in its box. - A double-click on a head's volume or pan sets it back to 0: the volume to 0 dB, the pan to the middle. It is one undo step of its own after the step the first click set. - Mute only lights its own button. The volume slider keeps its colour, so a muted head no longer looks out of step. Tests: - e2e 65 on melektaus-atx: ALL PASSED, 27 checks (+1) - typecheck, ESLint, Prettier: clean (also after the mute change) - screenshot on stein2: border above track 1, M and S with 4 px free above and below the letter in a 16 px button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
5b96d0b329 |
Paste under the pointer and pull song items out left in music tabs
A round of fixes to the Pattern and Song tabs: where a paste lands, what Shift does on a drag, how far the rows zoom, and how an item of a song is sized at its ends. - Shift does what Alt does on a drag: off the grid, on the tick. A Shift click on a note or an item still adds or unpicks it. A Shift press only decides on letting go: no drag toggles, a drag moves. - Ctrl+V lands under the pointer. The earliest copy goes on the grid line before it, the highest note on its row or the topmost item on its track, held to the keyboard or the tracks there are. Off the grid or left of bar 1 it lands at the start of playing as before. - The rows of the piano roll zoom to 64 px instead of 28, the tracks of a song to 320 px instead of 160. - Fit in the Pattern tab zooms the rows as well, so the notes fill the height, no longer held to the default of 14 px. - An item of a song can be pulled out by its left end past the start of what it plays, which then repeats. The offset goes round to the end of a round. A sound not loaded yet still stops at its start. - Both ends of an item snap to the start of a round of what it plays as well as to the grid, whichever is nearer. The end of a round between two ticks is cut to the tick before. A start put within half a tick of a round goes right on it, so it plays from the very beginning. - An offset past a whole round is not folded back to 0, so a pattern that grows later still plays from where the item said. - A middle-drag pans past the first and the last row, as it pans left of bar 1: the highest note or the first track up to half the height down, the other end up to half the height up. The room past them is dark in the piano roll and empty in the song. Tests: - Unit: song-edit 14, piano-roll 19, song 14 tests. New cases for the paste spot, pulling out left, the round snap and Fit. - e2e 64+65 on melektaus-atx: ALL PASSED - 54 checks (+4). New: Shift drag and Shift click, Ctrl+V under the pointer in both tabs, Fit zooming the rows, pulling a pattern out left and snapping a sound to the end of its second round. e2e 64 zooms the rows out again after Fit, so the keys it plays later are on screen. - Gate on melektaus-atx: 251 files, 3912 tests, CHECK EXIT 0. - Then the pan down the rows: e2e 64 on melektaus-atx ALL PASSED - 30 checks. Its pan check now also pans the top row down, half the grid's height, and a click above it draws nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
a3101c590c |
Size notes by either end and pan before bar one in music tabs
A round of small fixes to the Pattern and Song tabs: what the ruler and a pan do in both, and a few things the tabs carried that were in the way. - A middle-drag can take bar 1 up to half the grid or lanes in. The time before it is drawn dark on the ruler, the grid and the lanes. Nothing lands there: a click draws no note, a drop shows no frame. - A press or drag on the ruler puts the start on the nearest grid line, no longer on the one before the pointer. - A new song has one track instead of four. The "+ Track" row under the heads is gone, a head's menu adds tracks above or below. A song still keeps at least one, so that menu is always there. - A note can be sized by its left end too: the start goes to the nearest grid line and the end stays put, never before tick 0. - An end of a note under the pointer lights up and shows a resize cursor, as on an item of the Song tab. Tests: - Unit: piano-roll, song-edit, song, song-play 52 tests. Two new cases for the left end and the pan, the song fixtures add their tracks themselves now. - e2e 64+65 on melektaus-atx: ALL PASSED - 50 checks (+2). e2e 65 adds its tracks through the head's menu and clicks the ruler three quarters into a bar, which only the nearest line passes. - Gate on melektaus-atx: 251 files, 3909 tests, CHECK EXIT 0. - A probe shot of the piano roll panned in: the time before bar 1 dark, the left end of a note lit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
aa097bd076 |
Zoom with the wheel and set the loop on its own strip in music tabs
The ruler of the Pattern and Song tabs did two things with one drag,
and the wheel did three things with Alt and Shift. Both now do one
thing each, and the Song tab gets a few edits it was missing.
- The ruler has a loop strip along its top. A drag there sets the
loop, a press or drag below it moves only where playing starts.
- The wheel only zooms: the time over the grid, lanes and ruler, the
rows over the keys, the tracks over their heads. Alt and Shift no
longer change it. A middle-drag still pans.
- Tracks can be zoomed from 28 to 160 px. Below 46 px a head shows
only its name, M and S. An old saved view gets the old height.
- A click on nothing in the lanes picks the song itself.
- A right-click on an item opens a menu with Delete instead of
deleting it. The inspector has no delete buttons any more.
- A sound item goes up to +12 dB, a track up to +12 dB. A pattern
item stays at 0 dB, since a note is held to unity.
- An end of an item under the pointer lights up and shows a resize
cursor. A long item marks every point where it starts over.
- The Pattern tab has an Audition switch in its header, off at first.
Only with it on does a note sound when drawn, grabbed or moved.
The keys down the left sound either way.
- A looped sound item draws every round alike. Each round is drawn
from its own start, and each column shows the loudest part of the
sound it covers instead of one sampled bucket.
- A song is at least one bar long instead of four. An empty song
fits that bar across, and Play song ends after the last item.
- The ghost notes held back in #334 got their own issue, #339.
Finding: suite 542 for
|
||
|
|
8f9c250eb6 |
Lay patterns and sounds out on tracks and play them as a song #334
Patterns could only be heard one at a time, in their own tab or from a behavior. A song lays patterns and sounds out on tracks along one time axis and plays them through the scheduler of #332, the third piece of the music tools of #330. - New asset type song under the heading Songs, with four empty tracks, 120 BPM in 4/4 and a grid of a bar. Tempo, meter and grid are rows in the inspector. Tracks, items and the loop are the asset's data, held to their rules on load and in every command. - A track has a name, volume, pan, mute and solo. Each is heard on a bus of its own, so a change reaches what is sounding at once. - A pattern item repeats its pattern for as long as it is, with a transpose and another instrument if wanted. A sound item plays its sound as a clip at its own speed, round and round, through a sound FX if wanted. Both have a volume on top of their track's. - Cut back at the left end or split, an item starts as far into what it plays as the cut is: ticks into a pattern, seconds into a sound. - The tab shows the heads with M, S, volume and pan, the ruler of the Pattern tab and the items, a pattern with its notes, a sound with its waveform, a missing asset red. Patterns and sounds are dragged in from the Assets panel. Body, right and left end move, lengthen and cut back, Alt leaves the grid. Ctrl+C/V/D/A, Ctrl+E splits where playing starts, Delete, arrows. A double-click opens a pattern item in its tab. - What is picked is a new selection of its own, so the inspector shows the item or the track, with a button to delete it. - The scheduler plans clips beside notes. Where the playhead starts or jumps back inside a clip, it is taken up that far into its sound. A clip fades out at the end of its item or of the loop. - The editor plays one piece at a time: a pattern started stops the song and the other way round. - The rules are pure functions in core/music/song, editor/song/ songView and songEdit. Findings: - The suites of |