NoteHead.ts 3.7 KB

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