/
Notehead.ts
106 lines (98 loc) · 3.94 KB
/
Notehead.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { Note } from "./Note";
import log from "loglevel";
/**
* A note head with shape and fill information belonging to a [[Note]].
*/
export class Notehead {
/**
* @param sourceNote
* @param shapeTypeXml The shape type given from XML.
* See https://usermanuals.musicxml.com/MusicXML/Content/ST-MusicXML-notehead-value.htm
* @param filledXml The XML flag to fill the note shape. Can be undefined if not included in XML.
* If undefined, the filled parameter will be calculated by note duration (d < half note => filled)
*/
constructor(sourceNote: Note, shapeTypeXml: string, filledXml: boolean = undefined) {
this.sourceNote = sourceNote;
this.setShapeFromXml(shapeTypeXml, filledXml);
}
/** shape of the note head (normal, square, triangle, etc.) */
private shape: NoteHeadShape;
private filled: boolean;
/** the [[Note]] this NoteHead belongs to. */
private sourceNote: Note;
// note that color is stored in the sourceNote, because note.Notehead is undefined for normal noteheads.
/** Sets the note head's shape from XML parameters.
* @param shapeTypeXml The XML shape.
* @param filledXmlAttribute the filled parameter as given in XML.
* Can be undefined if not given in XML or if it should be calculated from note duration.
* If undefined, this.sourceNote should not be undefined.
*/
public setShapeFromXml(shapeTypeXml: string, filledXmlAttribute: boolean = undefined): void {
this.shape = Notehead.ShapeTypeXmlToShape(shapeTypeXml);
let filled: boolean = filledXmlAttribute;
if (filled === undefined) { // don't replace undefined check
if (!this.sourceNote) {
// this should not happen. Either filledXmlAttribute or sourceNote should be defined.
log.warn("notehead: sourceNote and filledXmlAttribute undefined.");
filled = true;
} else {
filled = this.sourceNote.Length.Denominator > 2;
}
}
this.filled = filled;
}
public get SourceNote(): Note {
return this.sourceNote;
}
public get Shape(): NoteHeadShape {
return this.shape;
}
public get Filled(): boolean {
return this.filled;
}
/** Converts xml attribute to NoteHeadShape.
* Necessary because "circle-x" is not a valid enum member name.
*/
public static ShapeTypeXmlToShape(shapeTypeXml: string): NoteHeadShape {
switch (shapeTypeXml.toLowerCase()) {
case "normal":
return NoteHeadShape.NORMAL;
case "x":
return NoteHeadShape.X;
case "slash":
return NoteHeadShape.SLASH;
case "diamond":
return NoteHeadShape.DIAMOND;
case "square":
return NoteHeadShape.SQUARE;
case "la": // Musescore displays this as a square
return NoteHeadShape.SQUARE;
case "do":
case "triangle":
return NoteHeadShape.TRIANGLE;
case "inverted triangle":
return NoteHeadShape.TRIANGLE_INVERTED;
case "rectangle":
return NoteHeadShape.RECTANGLE;
case "circle-x":
return NoteHeadShape.CIRCLEX;
default:
log.info("unsupported/unhandled xml notehead '" + shapeTypeXml + "'. Using normal notehead.");
return NoteHeadShape.NORMAL;
}
}
}
/** shape of a note head, needs to be supported by MusicXML and Vexflow. */
export enum NoteHeadShape {
CIRCLEX,
DIAMOND,
NORMAL,
RECTANGLE,
SLASH,
SQUARE,
TRIANGLE,
TRIANGLE_INVERTED,
X,
// TODO: Add the rest from https://usermanuals.musicxml.com/MusicXML/Content/ST-MusicXML-notehead-value.htm
// currently all Vexflow supported shapes present
}