-
Notifications
You must be signed in to change notification settings - Fork 676
Chord Symbols and Chord Changes
In VexFlow, the chord change module can create chord change symbols, like you'd see in a jazz or pop fake book.
To do this, it formats musical symbols (glyphs) from the rendering engine alongside ordinary text. To do that, it needs to know detailed information about the text font you're using. So chord changes will work best if you use one of the fonts that VexFlow knows about. Instructions for doing this, and adding additional text fonts, can be found later in this guide.
First we'll create a couple of chord symbols using the default browser-safe fonts. Note: this assumes you have read the VexFlow tutorial section on modifiers
To create a chord symbol and add it to a note:
const chord1 = new ChordSymbol()
.setFontSize(14)
.addText("B")
.addGlyph("b")
.addText("7", { symbolModifier: SymbolModifiers.SUPERSCRIPT })
.addGlyph("(", { symbolModifier: SymbolModifiers.SUPERSCRIPT })
.addGlyph("b", { symbolModifier: SymbolModifiers.SUPERSCRIPT })
.addText("5", { symbolModifier: SymbolModifiers.SUPERSCRIPT })
.addGlyph(")", { symbolModifier: SymbolModifiers.SUPERSCRIPT });
In the example above, we told VexFlow to create a chord with: the letter 'B' for the key, the glyph corresponding with the flat symbol, and the chord extension 7(♭5)
in superscript. See an example.
The example below shows how you can let VexFlow automatically select between glyphs and text:
const chord2 = new ChordSymbol().setFontSize(10).addGlyphOrText("Bb").addGlyphOrText("7(b5)", { symbolModifier: SymbolModifiers.SUPERSCRIPT });
staveNote.addModifier(chord2);
VexFlow automatically uses the flat symbol for 'b', the parentheses symbols ( and ), and text for the numbers and note names.
ChordSymbol
supports 15 symbols at present:
+ - ( ) b # /
result in the expected symbols, and other symbols can be specified explicitly with addGlyph()
:
'diminished', 'halfDiminished', 'leftParenTall', 'rightParenTall', 'majorSeventh', 'leftBracket', 'rightBracket'
You can see the ChordSymbol unit tests for more details.
What we've done so far looks kind of 'meh. The smaller image is a bit blurry, and the spacing between the notes isn't correct - this will cause problems for more complex formatting. Using a supported font will fix this.
The ChordSymbol
module supports two external text fonts at the time of this writing. The default font used depends on the engraving (music) font: If you use the music font Petaluma, the default text font is 'PetalumaScript' (both provided by Steinburg Media). Bravura and Gonville music fonts default to RobotoSlab, one of the Roboto family of web fonts provided by Google Fonts [ read more]. Both are provided under the SIL Open Font License [ read more].
To use the fonts in your application, the simplest way is to just include the css to download the font.
@font-face {
font-family: "petalumaScript";
src: url("https://aarondavidnewman.github.io/Smoosic/build/styles/fonts/petalumascript-webfont.woff2") format("woff2"), url("https://aarondavidnewman.github.io/Smoosic/build/styles/fonts/petalumascript-webfont.woff") format("woff");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: "robotoSlab";
src: url("https://aarondavidnewman.github.io/Smoosic/build/styles/fonts/robotoslab-webfont.woff2") format("woff2"), url("https://aarondavidnewman.github.io/Smoosic/build/styles/fonts/robotoslab-webfont.woff") format("woff");
font-weight: 500;
font-style: normal;
}
VexFlow will try to use 'robotoSlab' or 'petalumaScript' font, and fall back to 'Times' or 'Arial' respectively. You can also set the font explicitly for each chord, with this or any font you choose (see below on non-standard fonts):
var chord = new VF.ChordSymbol().setFont("robotoSlab", 15, "normal").addGlyphOrText("Bb7");
Now we'll try again [ run]:
That looks better. Now that we have fonts with some good formatting, we can do some more practical applications.
The last few examples show a superscript. As you'd expect, SymbolModifiers.SUBSCRIPT
gives you subscript. If you do superscript immediately followed by a subscript, the logic will align them vertically and stack them. See this example.
Try our the techniques in this sandbox.
You can put leftParenTall
and rightParenTall
on either side of the super/subscripts to get parenthesis on the full vertical extent of the chord.
var chord3 = new VF.ChordSymbol()
.addGlyphOrText("D")
.addGlyph("leftParenTall")
.addGlyphOrText("6", { symbolModifier: VF.ChordSymbol.symbolModifiers.SUPERSCRIPT })
.addGlyphOrText("9", { symbolModifier: VF.ChordSymbol.symbolModifiers.SUBSCRIPT })
.addGlyph("rightParenTall")
.setFontSize(14);
If you have an csymDiagonalArrangementSlash
symbol in your chord, the logic will try to condense your chord - moving the left side up and to the right, and the right side down and to the left (commonly spoken as 'C over F'):
var chord2 = new VF.ChordSymbol().addGlyphOrText("C").addGlyph("majorSeventh", { symbolModifier: VF.ChordSymbol.symbolModifiers.SUPERSCRIPT }).addGlyphOrText("/F");
Chords can be positioned: left/right/center of the note (horizontally) or above and below the note (vertically). Below may work nicely for music theory or figured base (My music theory years are far behind me so I'm not quite sure if these are right) [ run]:
chords.push(new VF.ChordSymbol().setVertical("bottom").addText("I").addTextSuperscript("6").addTextSubscript("4"));
// ...
chords.push(new VF.ChordSymbol().addLine(12).setVertical("bottom"));
You can also double stack on the top or the bottom. See the unit test cases for an example.
Just like with the browser default fonts, you can use any font you want. But you might have issues with the formatting, because VexFlow will still be using the metrics for the default fonts. Most English fonts will have a similar vertical baseline, but the spacing between the letters might vary, especially for longer strings or more florid typefaces.
Here's an example of using a font called Concert One. The formatting is a bit uneven, but for this example, at least, it works.
Load the web font with CSS:
@import url("https://fonts.googleapis.com/css2?family=Concert+One&display=swap");
Create a chord symbol object and set the font:
const chord = new ChordSymbol().addGlyphOrText("Ab").addGlyph("dim", { symbolModifier: SymbolModifiers.SUPERSCRIPT }).setFont("Concert One", 14, "normal");
The same VexFlow tools that extract glyphs from the music fonts can be used to extract the metrics from any OpenType text font:
- Download the font you like, and use a utility such as Font Squirrel to create a .otf (OpenType font) file.
- Place the file in the project directory
vexflow/tools/fonts/
, and run thefontgen_text.js
script. This will produce a .ts file with the formatting you want. For example:
node fontgen_text.js MyFont.otf myfont_glyphs.ts
- Move the
myfont_glyphs.ts
file tosrc/fonts/
, next to the other font glyphs files (petalumascript_glyphs.ts and robotoslab_glyphs.ts). - Update
src/fonts/textfonts.ts
to load the new font. - Optionally update elements to use the new text font by default. For example,
chordsymbol.ts
has aTEXT_FONT
property that returns its default text font.
Note: advanceWidth
and leftSideBearing
are the only metrics used currently.
[ VexFlow.com ] [ API ] [ GitHub Repo ] [ Contributors ]