vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature.
552 lines (551 loc) • 26.8 kB
JavaScript
import { concat, VexFlowTests } from './vexflow_test_helpers.js';
import { Beam } from '../src/beam.js';
import { Fraction } from '../src/fraction.js';
import { Stave } from '../src/stave.js';
import { Stem } from '../src/stem.js';
const AutoBeamFormattingTests = {
Start() {
QUnit.module('Auto-Beaming');
const run = VexFlowTests.runTests;
run('Simple Auto Beaming', simpleAuto);
run('Auto Beaming With Overflow Group', simpleAutoWithOverflowGroup);
run('Even Group Stem Directions', evenGroupStemDirections);
run('Odd Group Stem Directions', oddGroupStemDirections);
run('Odd Beam Groups Auto Beaming', oddBeamGroups);
run('More Simple Auto Beaming 0', moreSimple0);
run('More Simple Auto Beaming 1', moreSimple1);
run('Beam Across All Rests', beamAcrossAllRests);
run('Beam Across All Rests with Stemlets', beamAcrossAllRestsWithStemlets);
run('Break Beams on Middle Rests Only', beamAcrossMiddleRests);
run('Break Beams on Rest', breakBeamsOnRests);
run('Maintain Stem Directions', maintainStemDirections);
run('Maintain Stem Directions - Beam Over Rests', maintainStemDirectionsBeamAcrossRests);
run('Beat group with unbeamable note - 2/2', groupWithUnbeamableNote);
run('Offset beat grouping - 6/8 ', groupWithUnbeamableNote1);
run('Odd Time - Guessing Default Beam Groups', autoOddBeamGroups);
run('Custom Beam Groups', customBeamGroups);
run('Simple Tuplet Auto Beaming', simpleTuplets);
run('More Simple Tuplet Auto Beaming', moreSimpleTuplets);
run('More Automatic Beaming', moreBeaming);
run('Automatic Beaming 4/4 with 3, 3, 2 Pattern', beamingWithSeveralGroups1);
run('Automatic Beaming 4/4 with 3, 3, 2 Pattern and Overflow', beamingWithSeveralGroupsOverflow);
run('Automatic Beaming 8/4 with 3, 2, 3 Pattern and 2 Overflows', beamingWithSeveralGroupsOverflow2);
run('Automatic Beaming 8/4 with 3, 2, 3 Pattern and 3 Overflows', beamingWithSeveralGroupsOverflow3);
run('Duration-Based Secondary Beam Breaks', secondaryBreaks1);
run('Duration-Based Secondary Beam Breaks 2', secondaryBreaks2);
run('Flat Beams Up', flatBeamsUp);
run('Flat Beams Down', flatBeamsDown);
run('Flat Beams Mixed Direction', flatBeamsMixed);
run('Flat Beams Up (uniform)', flatBeamsUpUniform);
run('Flat Beams Down (uniform)', flatBeamsDownUniform);
run('Flat Beams Up Bounds', flatBeamsUpBounds);
run('Flat Beams Down Bounds', flatBeamsDownBounds);
},
};
function simpleAuto(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('f5/8, e5, d5, c5/16, c5, d5/8, e5, f5, f5/32, f5, f5, f5'), { time: '4/4' });
const beams = Beam.applyAndGetBeams(voice);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beaming Applicator Test');
}
function simpleAutoWithOverflowGroup(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('f5/4., e5/8, d5/8, d5/16, c5/16, c5/16, c5/16, f5/16, f5/32, f5/32'), {
time: '4/4',
});
const beams = Beam.applyAndGetBeams(voice);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beaming Applicator Test');
}
function evenGroupStemDirections(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('a4/8, b4, g4, c5, f4, d5, e4, e5, b4, b4, g4, d5'), { time: '6/4' });
const beams = Beam.applyAndGetBeams(voice);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.equal(beams[0].getStemDirection(), Stem.UP);
options.assert.equal(beams[1].getStemDirection(), Stem.UP);
options.assert.equal(beams[2].getStemDirection(), Stem.UP);
options.assert.equal(beams[3].getStemDirection(), Stem.UP);
options.assert.equal(beams[4].getStemDirection(), Stem.DOWN);
options.assert.equal(beams[5].getStemDirection(), Stem.DOWN);
options.assert.ok(true, 'Auto Beaming Applicator Test');
}
function oddGroupStemDirections(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('g4/8, b4, d5, c5, f4, d5, e4, g5, g4, b4, g4, d5, a4, c5, a4'), {
time: '15/8',
});
const groups = [new Fraction(3, 8)];
const beams = Beam.applyAndGetBeams(voice, undefined, groups);
options.assert.equal(beams[0].getStemDirection(), Stem.DOWN, 'Notes are equidistant from middle line');
options.assert.equal(beams[1].getStemDirection(), Stem.DOWN);
options.assert.equal(beams[2].getStemDirection(), Stem.UP);
options.assert.equal(beams[3].getStemDirection(), Stem.DOWN, 'Notes are equidistant from middle line');
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beaming Applicator Test');
}
function oddBeamGroups(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('f5, e5, d5, c5, c5, d5, e5, f5, f5, f4, f3, f5/16, f5'), { time: '6/4' });
const groups = [new Fraction(2, 8), new Fraction(3, 8), new Fraction(1, 8)];
const beams = Beam.applyAndGetBeams(voice, undefined, groups);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function moreSimple0(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c4/8, g4, c5, g5, a5, c4, d4, a5'), { time: '4/4' });
const beams = Beam.applyAndGetBeams(voice);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function moreSimple1(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'), { time: '4/4' });
const beams = Beam.applyAndGetBeams(voice);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function breakBeamsOnRests(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'), { time: '4/4' });
const beams = Beam.generateBeams(voice.getTickables(), {
beamRests: false,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function beamAcrossAllRestsWithStemlets(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'), { time: '4/4' });
const beams = Beam.generateBeams(voice.getTickables(), {
beamRests: true,
showStemlets: true,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function beamAcrossAllRests(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'), { time: '4/4' });
const beams = Beam.generateBeams(voice.getTickables(), {
beamRests: true,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function beamAcrossMiddleRests(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/16, g5, c5, c5/r, c5/r, (c4 e4 g4), d4, a5, c4, g4, c5, b4/r, (c4 e4), b4/r, b4/r, a4'), { time: '4/4' });
const beams = Beam.generateBeams(voice.getTickables(), {
beamRests: true,
beamMiddleOnly: true,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function maintainStemDirections(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes([
'b4/16, b4, b4[stem="down"], b4/r',
'b4/r, b4[stem="down"], b4, b4',
'b4[stem="down"], b4[stem="down"], b4, b4/r',
'b4/32, b4[stem="down"], b4[stem="down"], b4, b4/16/r, b4',
].join(', '), { stem: 'up' }), { time: '4/4' });
const beams = Beam.generateBeams(voice.getTickables(), {
beamRests: false,
maintainStemDirections: true,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function maintainStemDirectionsBeamAcrossRests(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes([
'b4/16, b4, b4[stem="down"], b4/r',
'b4/r, b4[stem="down"], b4, b4',
'b4[stem="down"], b4[stem="down"], b4, b4/r',
'b4/32, b4[stem="down"], b4[stem="down"], b4, b4/16/r, b4',
].join(', '), { stem: 'up' }), { time: '4/4' });
const beams = Beam.generateBeams(voice.getTickables(), {
beamRests: true,
maintainStemDirections: true,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function groupWithUnbeamableNote(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave().addTimeSignature('2/4');
const score = f.EasyScore();
const voice = score.voice(score.notes('b4/16, b4, b4/4, b4/16, b4'), { time: '2/4' });
const beams = Beam.generateBeams(voice.getTickables(), {
groups: [new Fraction(2, 2)],
beamRests: false,
maintainStemDirections: true,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function groupWithUnbeamableNote1(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave().addTimeSignature('6/8');
const score = f.EasyScore();
const voice = score.voice(score.notes('b4/4, b4/4, b4/8, b4/8'), { time: '6/8' });
const beams = Beam.generateBeams(voice.getTickables(), {
groups: [new Fraction(3, 8)],
beamRests: false,
maintainStemDirections: true,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function autoOddBeamGroups(options) {
const f = VexFlowTests.makeFactory(options, 450, 400);
const score = f.EasyScore();
const stave1 = f.Stave({ y: 10 }).addTimeSignature('5/4');
const voice1 = score.voice(score.notes('c5/8, g5, c5, b4, b4, c4, d4, a5, c4, g4'), { time: '5/4' });
const stave2 = f.Stave({ y: 150 }).addTimeSignature('5/8');
const voice2 = score.voice(score.notes('c5/8, g5, c5, b4, b4'), { time: '5/8' });
const stave3 = f.Stave({ y: 290 }).addTimeSignature('13/16');
const voice3 = score.voice(score.notes('c5/16, g5, c5, b4, b4, c5, g5, c5, b4, b4, c5, b4, b4'), {
time: '13/16',
});
const beams = [
...Beam.applyAndGetBeams(voice1, undefined, Beam.getDefaultBeamGroups('5/4')),
...Beam.applyAndGetBeams(voice2, undefined, Beam.getDefaultBeamGroups('5/8')),
...Beam.applyAndGetBeams(voice3, undefined, Beam.getDefaultBeamGroups('13/16')),
];
f.Formatter().formatToStave([voice1], stave1).formatToStave([voice2], stave2).formatToStave([voice3], stave3);
Stave.formatBegModifiers([stave1, stave2, stave3]);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function customBeamGroups(options) {
const f = VexFlowTests.makeFactory(options, 450, 400);
const score = f.EasyScore();
const stave1 = f.Stave({ y: 10 }).addTimeSignature('5/4');
const voice1 = score.voice(score.notes('c5/8, g5, c5, b4, b4, c4, d4, a5, c4, g4'), { time: '5/4' });
const stave2 = f.Stave({ y: 150 }).addTimeSignature('5/8');
const voice2 = score.voice(score.notes('c5/8, g5, c5, b4, b4'), { time: '5/8' });
const stave3 = f.Stave({ y: 290 }).addTimeSignature('13/16');
const voice3 = score.voice(score.notes('c5/16, g5, c5, b4, b4, c5, g5, c5, b4, b4, c5, b4, b4'), { time: '13/16' });
const group1 = [new Fraction(5, 8)];
const group2 = [new Fraction(3, 8), new Fraction(2, 8)];
const group3 = [new Fraction(7, 16), new Fraction(2, 16), new Fraction(4, 16)];
const beams = [
...Beam.applyAndGetBeams(voice1, undefined, group1),
...Beam.applyAndGetBeams(voice2, undefined, group2),
...Beam.applyAndGetBeams(voice3, undefined, group3),
];
f.Formatter().formatToStave([voice1], stave1).formatToStave([voice2], stave2).formatToStave([voice3], stave3);
Stave.formatBegModifiers([stave1, stave2, stave3]);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function createShortcuts(score) {
return {
notes: score.notes.bind(score),
tuplet: score.tuplet.bind(score),
};
}
function simpleTuplets(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const { notes, tuplet } = createShortcuts(score);
const voice = score.voice([
...tuplet(notes('c4/8, g4, c5')),
...notes('g5/8, a5'),
...tuplet(notes('a5/16, (c5 e5), a5, d5, a5'), { ratioed: false, notesOccupied: 4 }),
], { time: '3/4' });
const beams = Beam.applyAndGetBeams(voice);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function moreSimpleTuplets(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const { notes, tuplet } = createShortcuts(score);
const voice = score.voice([...tuplet(notes('d4/4, g4, c5')), ...notes('g5/16, a5, a5, (c5 e5)')], { time: '3/4' });
const beams = Beam.applyAndGetBeams(voice);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function moreBeaming(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c4/8, g4/4, c5/8., g5/16, a5/4, a5/16, (c5 e5)/16, a5/8'), { time: '9/8' });
const beams = Beam.applyAndGetBeams(voice, undefined, Beam.getDefaultBeamGroups('9/8'));
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function beamingWithSeveralGroups1(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c4/8, g4/4, c5/8, g5, a5, a5, f5'), { time: '4/4' });
const beams = Beam.applyAndGetBeams(voice, undefined, [new Fraction(3, 8), new Fraction(3, 8), new Fraction(2, 8)]);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function beamingWithSeveralGroupsOverflow(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c4/8, g4/4., c5/8, g5, a5, a5'), { time: '4/4' });
const beams = Beam.applyAndGetBeams(voice, undefined, [new Fraction(3, 8), new Fraction(3, 8), new Fraction(2, 8)]);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function beamingWithSeveralGroupsOverflow2(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c4/16, g4/2, f4/16, c5/8, a4/16, c4/16, g4/8, b4, c5, g5, f5, e5, c5, a4/4'), {
time: '8/4',
});
const beams = Beam.applyAndGetBeams(voice, undefined, [new Fraction(3, 8), new Fraction(2, 8), new Fraction(3, 8)]);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function beamingWithSeveralGroupsOverflow3(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes('c4/16, g4/1, f4/16, c5/8, g5, f5, e5, c5, a4/4'), { time: '8/4' });
const beams = Beam.applyAndGetBeams(voice, undefined, [new Fraction(3, 8), new Fraction(2, 8), new Fraction(3, 8)]);
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Auto Beam Applicator Test');
}
function secondaryBreaks1(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const voice = score.voice(score.notes([
'f5/32, f5, f5, f5, f5/16., f5/32',
'f5/16, f5/8, f5/16',
'f5/32, f5/16., f5., f5/32',
'f5/16., f5/32, f5, f5/16.',
].join(',')));
const beams = Beam.generateBeams(voice.getTickables(), { secondaryBreaks: '8' });
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Duration-Based Secondary Breaks Test');
}
function secondaryBreaks2(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave();
const score = f.EasyScore();
const { notes, tuplet } = createShortcuts(score);
const voice = score.voice([
tuplet(notes('e5/16, f5, f5')),
tuplet(notes('f5/16, f5, c5')),
notes('a4/16., f4/32'),
tuplet(notes('d4/16, d4, d4')),
tuplet(notes('a5/8, (e5 g5), a5')),
tuplet(notes('f5/16, f5, f5')),
tuplet(notes('f5/16, f5, a4')),
].reduce(concat));
const beams = Beam.generateBeams(voice.getTickables(), { secondaryBreaks: '8' });
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Duration-Based Secondary Breaks Test');
}
function flatBeamsUp(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave({ y: 40 });
const score = f.EasyScore();
const { notes, tuplet } = createShortcuts(score);
const voice = score.voice([
tuplet(notes('c4/8, g4, f5')),
notes('d5/8'),
tuplet(notes('c5/16, (c4 e4 g4), f4')),
notes('d5/8, e5, c4, f5/32, f5, f5, f5'),
].reduce(concat));
const beams = Beam.generateBeams(voice.getTickables(), {
flatBeams: true,
stemDirection: 1,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Flat Beams Up Test');
}
function flatBeamsDown(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave({ y: 40 });
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/64, c5, c5, c5, c5, c5, c5, c5, a5/8, g5, (d4 f4 a4)/16, d4, d5/8, e5, g5, a6/32, a6, a6, g4/64, g4'));
const beams = Beam.generateBeams(voice.getTickables(), {
flatBeams: true,
stemDirection: -1,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Flat Beams Down Test');
}
function flatBeamsMixed(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave({ y: 40 });
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/64, d5, e5, c5, f5, c5, a5, c5, a5/8, g5, (d4 f4 a4)/16, d4, d5/8, e5, c4, a4/32, a4, a4, g4/64, g4'));
const beams = Beam.generateBeams(voice.getTickables(), { flatBeams: true });
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Flat Beams Mixed Direction Test');
}
function flatBeamsUpUniform(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave({ y: 40 });
const score = f.EasyScore();
const { notes, tuplet } = createShortcuts(score);
const voice = score.voice([
...tuplet(notes('c4/8, g4, g5')),
...notes('d5/8, c5/16, (c4 e4 g4), d5/8, e5, c4, f5/32, f5, f5, f5'),
]);
const beams = Beam.generateBeams(voice.getTickables(), {
flatBeams: true,
flatBeamOffset: 50,
stemDirection: 1,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Flat Beams Up (uniform) Test');
}
function flatBeamsDownUniform(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave({ y: 40 });
const score = f.EasyScore();
const voice = score.voice(score.notes('c5/64, c5, c5, c5, c5, c5, c5, c5, a5/8, g5, (e4 g4 b4)/16, e5, d5/8, e5/8, g5/8, a6/32, a6, a6, g4/64, g4'));
const beams = Beam.generateBeams(voice.getTickables(), {
flatBeams: true,
flatBeamOffset: 155,
stemDirection: -1,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Flat Beams Down (uniform) Test');
}
function flatBeamsUpBounds(options) {
const f = VexFlowTests.makeFactory(options);
const stave = f.Stave({ y: 40 });
const score = f.EasyScore();
const { notes, tuplet } = createShortcuts(score);
const voice = score.voice([
...tuplet(notes('c4/8, g4/8, g5/8')),
...notes('d5/8, c5/16, (c4 e4 g4)/16, d5/8, e5/8, c4/8, f5/32, f5/32, f5/32, f5/32'),
]);
const beams = Beam.generateBeams(voice.getTickables(), {
flatBeams: true,
flatBeamOffset: 60,
stemDirection: 1,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Flat Beams Up (uniform) Test');
}
function flatBeamsDownBounds(options) {
const f = VexFlowTests.makeFactory(options, 450, 200);
const stave = f.Stave({ y: 40 });
const score = f.EasyScore();
const voice = score.voice(score.notes([
'g5/8, a6/32, a6/32, a6/32, g4/64, g4/64',
'c5/64, c5/64, c5/64, c5/64, c5/64, c5/64, c5/64, c5/64, a5/8',
'g5/8, (e4 g4 b4)/16, e5/16',
'd5/8, e5/8',
].join(','), { stem: 'down' }));
const beams = Beam.generateBeams(voice.getTickables(), {
flatBeams: true,
flatBeamOffset: 145,
stemDirection: -1,
});
f.Formatter().joinVoices([voice]).formatToStave([voice], stave);
f.draw();
beams.forEach((beam) => beam.setContext(f.getContext()).drawWithStyle());
options.assert.ok(true, 'Flat Beams Down (uniform) Test');
}
VexFlowTests.register(AutoBeamFormattingTests);
export { AutoBeamFormattingTests };