A song track can now change its volume and pan over time, played on the audio clock wherever the song is heard. This is stage 1 of #337: the model and the playback. Lanes cannot be drawn in the song tab yet. - A track holds automation lanes for volume (dB) and pan. Each point has a tick, a value and an easing from the shared list, curve assets included. Two points on one tick make a jump. Before the first point its value holds, after the last point the last value holds. - The rules are pure functions in core/music/automation.ts: the value at a tick and the pieces of a lane inside one scheduling window. - The scheduler hands those pieces to the host in every window. The host sets them as ramps or jumps on the gain and panner of the track's bus. Shapes the clock cannot ramp directly (dB as gain, curved easings) are sampled every 10 ms. At the loop end the value jumps back with the playhead. - This works in the song tab, for Play song, inside a composition (across the song loop, on the item's own bus) and in a bake. - While a lane has points the fader no longer sets that value. When the lane goes, the fader takes over from the current value. - Automation enters the bake fingerprint only when there is some, so existing bakes stay valid. - The level helpers moved to core/music/level.ts, so song.ts and automation.ts do not import each other. Known gap: a delaying sound FX on a bus after the track (a pitch shifter) makes the automation late by that delay. Tests: - automation.test.ts (13, new), 3 new in sound-library.test.ts. Song, bake and composition tests together 286/286. - 12 counter-checks, all compile, all red. - e2e 65 on atx: ALL PASSED, 60 checks. New 65h2: in the song tab the bus level follows a volume lane, 0.09 dB off, also with the fader at -60 dB. Red when the song tab does not pass the automation on. - Gate on atx: 328 files, 5053 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8 lines
254 B
TypeScript
8 lines
254 B
TypeScript
/** The volume of a track of a song (#334), in decibels; at the lowest it is silent. */
|
|
export const TRACK_MIN_DB = -60;
|
|
export const TRACK_MAX_DB = 12;
|
|
|
|
export function dbToGain(db: number): number {
|
|
return db <= TRACK_MIN_DB ? 0 : 10 ** (db / 20);
|
|
}
|