Snap a new song to 1/16, and route new assets as the others (#365)
A new song snapped to whole bars, too coarse to lay out a beat. And a new or duplicated sound, instrument, pattern or song went to the master alone, so every one had to be linked into the buses by hand again. - A song without a grid of its own snaps to 1/16. The songs in the user's project have Bar written in and keep it. - A new or duplicated sound, instrument, pattern or song gets the links of the one whose targets most others of its type share, at their volume. On a tie the latest of them decides, so a single song decides for the next one. - Where nothing of its type is linked yet, it goes as most of all that plays, and where nothing is, to the master. A new bus still goes to the master alone. - Assets made at once are matched against what stood before, not against each other. A project from before the routing still opens with everything on the master. - The song tab has a gridAt hook. e2e 65 checks the new grid and sets Bar, which its checks go by. Tests: - Unit master-routing (1 new) and song (1 rewritten): 26 green. Counter checks (rule off, grid back to Bar) red. - e2e 65 (melektaus-atx): ALL PASSED, 58 checks (1 new). - Gate (melektaus-atx): CHECK EXIT 0, 273 files, 4226 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0e73fd85b9
commit
f840ec3c44
7 files changed
+131
-11
No files matched your search
@@ -7,6 +7,7 @@ import {
|
||||
CreateAssetCommand,
|
||||
CreateSoundCommand,
|
||||
DeleteAssetCommand,
|
||||
DuplicateAssetCommand,
|
||||
RenameAssetCommand,
|
||||
} from '../../src/core/commands/assetCommands';
|
||||
import type { Command } from '../../src/core/commands/Command';
|
||||
@@ -80,6 +81,50 @@ describe('the nodes of the master routing (#351)', () => {
|
||||
expect([at(MASTER_BUS).x, at(MASTER_BUS).y]).toEqual([640, -80]);
|
||||
});
|
||||
|
||||
it('link a new or duplicated asset where most others of its type go, else where all that plays goes', () => {
|
||||
const f = edited();
|
||||
const reverb = f.create('bus', 'Reverb');
|
||||
const drums = f.create('bus', 'Drums');
|
||||
const kick = f.sound('Kick');
|
||||
const snare = f.sound('Snare');
|
||||
const hat = f.sound('Hat');
|
||||
const offMaster = (id: string) =>
|
||||
f.run(new DisconnectCommand(ROUTING_ID, f.project.routing.edges.find((e) => e.from.node === id)!.id));
|
||||
// Two sounds go into Drums and Reverb, one into the master alone: a new one goes with the two.
|
||||
for (const id of [kick, snare]) {
|
||||
offMaster(id);
|
||||
f.link(id, drums);
|
||||
f.run(new SetSendCommand(ROUTING_ID, f.link(id, reverb), { volume: -9, tap: 'post' }));
|
||||
}
|
||||
const tom = f.sound('Tom');
|
||||
expect(f.linksOf(tom).sort()).toEqual([drums, reverb].sort());
|
||||
const sendTo = (id: string, to: string) =>
|
||||
f.project.routing.edges.find((e) => e.from.node === id && e.to.node === to)?.send;
|
||||
expect(sendTo(tom, reverb)).toEqual({ volume: -9, tap: 'post' });
|
||||
const copy = new DuplicateAssetCommand(hat);
|
||||
f.run(copy);
|
||||
expect(f.linksOf(copy.copyId).sort()).toEqual([drums, reverb].sort());
|
||||
expect(f.linksOf(hat)).toEqual([MASTER_BUS]);
|
||||
|
||||
// The first song goes as most that plays; the one song there is then decides for the next.
|
||||
const theme = f.create('song', 'Theme');
|
||||
expect(f.linksOf(theme).sort()).toEqual([drums, reverb].sort());
|
||||
f.run(
|
||||
new DisconnectCommand(
|
||||
ROUTING_ID,
|
||||
f.project.routing.edges.find((e) => e.from.node === theme && e.to.node === drums)!.id,
|
||||
),
|
||||
);
|
||||
expect(f.linksOf(f.create('song', 'Outro'))).toEqual([reverb]);
|
||||
expect(f.linksOf(f.create('pattern', 'Riff')).sort()).toEqual([drums, reverb].sort());
|
||||
// A bus goes to the master as before.
|
||||
expect(f.linksOf(f.create('bus', 'Delay'))).toEqual([MASTER_BUS]);
|
||||
// Undone, a new asset takes its links along.
|
||||
const links = f.project.routing.edges.length;
|
||||
f.stack.undo();
|
||||
expect(f.project.routing.edges.length).toBe(links - 1);
|
||||
});
|
||||
|
||||
it('come in by type as a project from before the routing is opened', () => {
|
||||
const f = makeProject();
|
||||
for (const command of [
|
||||
|
||||
@@ -67,11 +67,13 @@ function makeSong(tracks = 4) {
|
||||
}
|
||||
|
||||
describe('the song asset (#334)', () => {
|
||||
it('starts with one track, nothing on it, at 120 BPM in 4/4 on a grid of a bar', () => {
|
||||
it('starts with one track, nothing on it, at 120 BPM in 4/4 on a grid of 1/16', () => {
|
||||
const f = makeSong(1);
|
||||
expect(f.song().tracks.map((t) => t.name)).toEqual(['Track 1']);
|
||||
expect(f.song().items).toEqual([]);
|
||||
expect(schemaForAsset(f.project, f.song()).map((d) => d.key)).toEqual(['tempo', 'sign', 'grid', 'fx']);
|
||||
expect(songGrid(f.song().props)).toBe(120);
|
||||
f.stack.execute(new SetAssetPropertyCommand(f.song().id, 'grid', 'bar'));
|
||||
expect(songGrid(f.song().props)).toBe(BAR);
|
||||
f.stack.execute(new SetAssetPropertyCommand(f.song().id, 'grid', '1/8T'));
|
||||
expect(songGrid(f.song().props)).toBe(160);
|
||||
|
||||
Reference in new issue
Block a user