A game should be able to start the next piece of music when one is
over, or wait for a sound before it goes on. Until now a behavior
could start and stop music and sounds, but never learn that they had
ended.
- Two new events: On music finished with the fields Song and Pattern
and the input playback, and On sound finished with the field Sound
and the input voice. Both give out what ended and stopped.
- Two new data nodes, Music playing and Sound playing, ask whether
something is still heard.
- Over means nothing is heard any more: no tail of the effects, and
a fade-out has run down.
- stopped is on for Stop song, pattern or sound, when the behavior
that owns it ends and on a scene change. For a sound also when a
newer voice needs its place or the file does not load.
- Only what the Play nodes of this run started is heard, across
scene changes too. Previews in the tabs, compositions and notes of
instruments do not count.
- Switch song ends nothing. The number goes on, and the end is told
under the song heard last.
- Playbacks and the SoundLibrary tell each end once to a new
PlayedEnds per run. The AudioSwitch passes them on from both sinks.
Found and fixed: a pattern whose last bar ends in silence counted as
done up to one planning window before its end. In e2e 65 the next
pattern started after 1.962 s instead of 2 s. Scheduler.done now also
wants the playhead to have reached the end. Cleaning up done
playbacks therefore comes a few tenths of a second later. One test
that expected the early end is adjusted.
Tests:
- Unit: 23 new (played-ends 12, sound-library 5, node catalog 5,
audio-switch 1), all green.
- Counter-probes: 19 bends, all red. One was green at first for want
of a case, which is added now.
- e2e 65 on atx: ALL PASSED, 78 checks. New 65k6: the event came
once with stopped off, and the second pattern started 2.051 s after
the stinger. Stop song gave exactly one end with stopped on, and
the switch from 65k3 gave none.
- Gate on atx: CHECK EXIT 0, 337 files, 5222 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A stinger has to start on the next beat or bar of the song that is
playing, not whenever the frame happens to run. Play sound, Play note
and Play pattern now take the number of a song or pattern playback and
plan their start on the audio clock, as the music is heard.
- New inputs sync (a playback number) and quantize (Next bar by
default, decision 6) on Play sound, Play note and Play pattern.
- The landing is worked out in Playbacks (landOn), on the next beat,
bar or marker of the playback as it is heard. SoundLibrary and the
audio switch only pass it on, and only on the clock the stinger
plays on.
- A pattern with sync plays in the tempo of the playback. It takes its
bake only when both tempos match.
- Without a link, or when the playback is not heard, the node starts
at once as before.
- The sync ports live in their own module musicSync.ts. Putting them
in songSync.ts would have made an import cycle through Play song.
Tests:
- Unit: 8 new (6 in song-play, 1 each in sound-library and
audio-switch), all green.
- Counter-probes: 12 bends, all red.
- e2e 65 on atx: ALL PASSED, 74 checks. New 65k4: the pattern (own
tempo 100) started exactly 8 beats after the song and played at the
song's 120 BPM. Without sync it is red (6.2 beats, 100 BPM).
- Gate on atx: CHECK EXIT 0, 334 files, 5152 tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 4K and 60 fps the user's computer reaches about 39 fps in real time.
Reading each frame back from the GPU takes longer than a frame, and
neither reading back later nor the canvas route helped. With Real time
off the run moves on by one frame of the recording at a time, however
long the computer takes, so the file has every frame.
- Start recording has a new check Real time, on by default. Only the
node records so, the editor recording stays in real time.
- SteadyPace in recording.ts is the pace as a pure class. A step is
1/fps once the frame before is taken and the sound up to it is made,
otherwise 0 and the run holds. A frame's time is its number.
- The sound is made apart, as decided in the issue. AudioSwitch routes
what the run plays to the live library, or to the offline library of
a SteadySound while such a recording lasts. That library has the same
mix, buses, FX and limiter and is rendered up to each next frame.
- A driven video holds at every picture asked for, and the frame waits
for it. Its sound is decoded from the MP4 and played in step through
its bus.
- Two Chrome quirks measured and worked around. A held video hands
over the picture of a seek before seeked, so the frame callback is
asked for when the seek begins. A seek right onto where a picture
begins shows that one or the one before, so such a seek lands half a
millisecond further. Together 30 s became 10.7 s for 2 s of video.
- The notice tells how far the recording has got, and the line at the
end how long it took.
Deviations and limits:
- Input is not ignored, it still reaches the game, which runs slower.
- At most ten minutes per recording. Chrome holds the whole buffer of
the OfflineAudioContext while rendering, 230 MB for ten minutes.
- A free video plays on in real time and does not fit. A sound playing
before the start stays at the speakers.
Found along the way:
- A check in e2e 60 was red since 77365f1. It expected one log line,
the start line of the recording came on top. CI was off, so nobody
saw it. The expectation is updated.
Tests:
- First gate run red: 1 test in node-catalog.test.ts still expected
the settings of Start recording without realTime. Updated.
- Second gate run on melektaus-atx green: 310 files,
4818 tests.
- e2e 66 + 68 all passed, 50 checks, 68j new with 3 checks. ffmpeg
reads all 120 frames 1/60 s apart, the colour changes at frames
30/60/90, the video's sound from the first frame, the blip 8 ms off.
- e2e 60 (20 checks) and 67 green.
- Counter-check without the pace: all three 68j checks red, 32 of 119
frames, colour changes at 33/62/96, no sound. AudioSwitch's unit test
goes red when the ids are mixed up.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>