vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature
342 lines (288 loc) • 16.1 kB
JavaScript
/**
* VexFlow - Articulation Tests
* Copyright Mohit Muthanna 2010 <mohit@muthanna.com>
*/
var VF = Vex.Flow;
VF.Test.Articulation = (function() {
var Articulation = {
Start: function() {
QUnit.module('Articulation');
Articulation.runTests('Articulation - Staccato/Staccatissimo', 'a.', 'av', Articulation.drawArticulations);
Articulation.runTests('Articulation - Accent/Tenuto', 'a>', 'a-', Articulation.drawArticulations);
Articulation.runTests('Articulation - Marcato/L.H. Pizzicato', 'a^', 'a+', Articulation.drawArticulations);
Articulation.runTests('Articulation - Snap Pizzicato/Fermata', 'ao', 'ao', Articulation.drawArticulations);
Articulation.runTests('Articulation - Up-stroke/Down-Stroke', 'a|', 'am', Articulation.drawArticulations);
Articulation.runTests('Articulation - Fermata Above/Below', 'a@a', 'a@u', Articulation.drawFermata);
Articulation.runTests('Articulation - Inline/Multiple', 'a.', 'a.', Articulation.drawArticulations2);
Articulation.runTests('TabNote Articulation', 'a.', 'a.', Articulation.tabNotes);
},
runTests: function(name, sym1, sym2, func) {
var params = {
sym1: sym1,
sym2: sym2,
};
VF.Test.runTests(name, func, params);
},
drawArticulations: function(options, contextBuilder) {
var sym1 = options.params.sym1;
var sym2 = options.params.sym2;
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 625, 195);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 125);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['a/3'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
];
notesBar1[0].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
notesBar1[1].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
notesBar1[2].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar1[3].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x, staveBar1.y, 125);
staveBar2.setEndBarType(VF.Barline.type.DOUBLE);
staveBar2.setContext(ctx).draw();
var notesBar2 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
notesBar2[0].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[1].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[2].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
notesBar2[3].addArticulation(0, new VF.Articulation(sym1).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
// bar 3 - juxtaposing second bar next to first bar
var staveBar3 = new VF.Stave(staveBar2.width + staveBar2.x, staveBar2.y, 125);
staveBar3.setContext(ctx).draw();
var notesBar3 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
];
notesBar3[0].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar3[1].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar3[2].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
notesBar3[3].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar3, notesBar3);
// bar 4 - juxtaposing second bar next to first bar
var staveBar4 = new VF.Stave(staveBar3.width + staveBar3.x, staveBar3.y, 125);
staveBar4.setEndBarType(VF.Barline.type.END);
staveBar4.setContext(ctx).draw();
var notesBar4 = [
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
notesBar4[0].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
notesBar4[1].addArticulation(0, new VF.Articulation(sym2).setPosition(3));
notesBar4[2].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar4[3].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar4, notesBar4);
},
drawFermata: function(options, contextBuilder) {
var sym1 = options.params.sym1;
var sym2 = options.params.sym2;
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 400, 200);
// bar 1
var staveBar1 = new VF.Stave(50, 30, 150);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/4'], duration: 'q', stem_direction: -1 }),
];
notesBar1[0].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar1[1].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar1[2].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar1[3].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x, staveBar1.y, 150);
staveBar2.setEndBarType(VF.Barline.type.DOUBLE);
staveBar2.setContext(ctx).draw();
var notesBar2 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
notesBar2[0].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[1].addArticulation(0, new VF.Articulation(sym1).setPosition(3));
notesBar2[2].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
notesBar2[3].addArticulation(0, new VF.Articulation(sym2).setPosition(4));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
},
drawArticulations2: function(options, contextBuilder) {
expect(0);
// Get the rendering context
var ctx = contextBuilder(options.elementId, 1000, 200);
// bar 1
var staveBar1 = new VF.Stave(10, 30, 350);
staveBar1.setContext(ctx).draw();
var notesBar1 = [
new VF.StaveNote({ keys: ['c/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['d/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['e/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['g/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['b/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/5'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['d/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['e/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['f/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['g/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['b/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/6'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['d/6'], duration: '16', stem_direction: -1 }),
];
var i;
for (i = 0; i < 16; i++) {
notesBar1[i].addArticulation(0, new VF.Articulation('a.').setPosition(4));
notesBar1[i].addArticulation(0, new VF.Articulation('a>').setPosition(4));
if (i === 15) {
notesBar1[i].addArticulation(0, new VF.Articulation('a@u').setPosition(4));
}
}
var beam1 = new VF.Beam(notesBar1.slice(0, 8));
var beam2 = new VF.Beam(notesBar1.slice(8, 16));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar1, notesBar1);
beam1.setContext(ctx).draw();
beam2.setContext(ctx).draw();
// bar 2 - juxtaposing second bar next to first bar
var staveBar2 = new VF.Stave(staveBar1.width + staveBar1.x, staveBar1.y, 350);
staveBar2.setContext(ctx).draw();
var notesBar2 = [
new VF.StaveNote({ keys: ['f/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['g/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['a/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['b/3'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['c/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['d/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['e/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['f/4'], duration: '16', stem_direction: 1 }),
new VF.StaveNote({ keys: ['g/4'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/4'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['b/4'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['d/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['e/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['f/5'], duration: '16', stem_direction: -1 }),
new VF.StaveNote({ keys: ['g/5'], duration: '16', stem_direction: -1 }),
];
for (i = 0; i < 16; i++) {
notesBar2[i].addArticulation(0, new VF.Articulation('a-').setPosition(3));
notesBar2[i].addArticulation(0, new VF.Articulation('a^').setPosition(3));
if (i === 15) {
notesBar2[i].addArticulation(0, new VF.Articulation('a@u').setPosition(4));
}
}
var beam3 = new VF.Beam(notesBar2.slice(0, 8));
var beam4 = new VF.Beam(notesBar2.slice(8, 16));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar2, notesBar2);
beam3.setContext(ctx).draw();
beam4.setContext(ctx).draw();
// bar 3 - juxtaposing second bar next to first bar
var staveBar3 = new VF.Stave(staveBar2.width + staveBar2.x, staveBar2.y, 75);
staveBar3.setContext(ctx).draw();
var notesBar3 = [
new VF.StaveNote({ keys: ['c/4'], duration: 'w', stem_direction: 1 }),
];
notesBar3[0].addArticulation(0, new VF.Articulation('a-').setPosition(3));
notesBar3[0].addArticulation(0, new VF.Articulation('a>').setPosition(3));
notesBar3[0].addArticulation(0, new VF.Articulation('a@a').setPosition(3));
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar3, notesBar3);
// bar 4 - juxtaposing second bar next to first bar
var staveBar4 = new VF.Stave(staveBar3.width + staveBar3.x, staveBar3.y, 150);
staveBar4.setEndBarType(VF.Barline.type.END);
staveBar4.setContext(ctx).draw();
var notesBar4 = [
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['c/5'], duration: 'q', stem_direction: -1 }),
new VF.StaveNote({ keys: ['a/5'], duration: 'q', stem_direction: -1 }),
];
for (i = 0; i < 4; i++) {
var position1 = 3;
if (i > 1) {
position1 = 4;
}
notesBar4[i].addArticulation(0, new VF.Articulation('a-').setPosition(position1));
}
// Helper function to justify and draw a 4/4 voice
VF.Formatter.FormatAndDraw(ctx, staveBar4, notesBar4);
},
tabNotes: function(options, contextBuilder) {
var ctx = new contextBuilder(options.elementId, 600, 200);
ctx.font = '10pt Arial';
var stave = new VF.TabStave(10, 10, 550);
stave.setContext(ctx);
stave.draw();
var specs = [
{ positions: [{ str: 3, fret: 6 }, { str: 4, fret: 25 }], duration: '8' },
{ positions: [{ str: 2, fret: 10 }, { str: 5, fret: 12 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 3, fret: 5 }], duration: '8' },
{ positions: [{ str: 1, fret: 6 }, { str: 3, fret: 5 }], duration: '8' },
];
var notes = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
return tabNote;
});
var notes2 = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
tabNote.render_options.draw_stem = true;
tabNote.setStemDirection(-1);
return tabNote;
});
var notes3 = specs.map(function(noteSpec) {
var tabNote = new VF.TabNote(noteSpec);
return tabNote;
});
notes[0].addModifier(new VF.Articulation('a>').setPosition(3), 0); // U
notes[1].addModifier(new VF.Articulation('a>').setPosition(4), 0); // D
notes[2].addModifier(new VF.Articulation('a.').setPosition(3), 0); // U
notes[3].addModifier(new VF.Articulation('a.').setPosition(4), 0); // D
notes2[0].addModifier(new VF.Articulation('a>').setPosition(3), 0);
notes2[1].addModifier(new VF.Articulation('a>').setPosition(4), 0);
notes2[2].addModifier(new VF.Articulation('a.').setPosition(3), 0);
notes2[3].addModifier(new VF.Articulation('a.').setPosition(4), 0);
notes3[0].addModifier(new VF.Articulation('a>').setPosition(3), 0);
notes3[1].addModifier(new VF.Articulation('a>').setPosition(4), 0);
notes3[2].addModifier(new VF.Articulation('a.').setPosition(3), 0);
notes3[3].addModifier(new VF.Articulation('a.').setPosition(4), 0);
var voice = new VF.Voice(VF.Test.TIME4_4).setMode(VF.Voice.Mode.SOFT);
voice.addTickables(notes);
voice.addTickables(notes2);
voice.addTickables(notes3);
new VF.Formatter()
.joinVoices([voice])
.formatToStave([voice], stave);
voice.draw(ctx, stave);
ok(true, 'TabNotes successfully drawn');
},
};
return Articulation;
}());