Jelajahi Sumber

fix(grace notes): can be at end of measure, after main note

sschmidTU 6 tahun lalu
induk
melakukan
37f145dc5a

+ 12 - 3
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -632,10 +632,12 @@ export class VexFlowMeasure extends GraphicalMeasure {
     }
 
     public graphicalMeasureCreatedCalculations(): void {
+        let graceSlur: boolean;
+        let graceGVoiceEntriesBefore: GraphicalVoiceEntry[];
         for (const graphicalStaffEntry of this.staffEntries as VexFlowStaffEntry[]) {
+            graceSlur = false;
+            graceGVoiceEntriesBefore = [];
             // create vex flow Stave Notes:
-            let graceSlur: boolean = false;
-            let graceGVoiceEntriesBefore: GraphicalVoiceEntry[] = [];
             for (const gve of graphicalStaffEntry.graphicalVoiceEntries) {
                 if (gve.parentVoiceEntry.IsGrace) {
                     graceGVoiceEntriesBefore.push(gve);
@@ -667,6 +669,13 @@ export class VexFlowMeasure extends GraphicalMeasure {
                 }
             }
         }
+        // remaining grace notes at end of measure, turned into stand-alone grace notes:
+        if (graceGVoiceEntriesBefore.length > 0) {
+            for (const graceGve of graceGVoiceEntriesBefore) {
+                (graceGve as VexFlowVoiceEntry).vfStaveNote = VexFlowConverter.StaveNote(graceGve);
+                graceGve.parentVoiceEntry.GraceAfterMainNote = true;
+            }
+        }
 
         this.finalizeBeams();
         this.finalizeTuplets();
@@ -690,7 +699,7 @@ export class VexFlowMeasure extends GraphicalMeasure {
             // create vex flow voices and add tickables to it:
             for (const voiceEntry of restFilledEntries) {
                 if (voiceEntry.parentVoiceEntry) {
-                    if (voiceEntry.parentVoiceEntry.IsGrace) {
+                    if (voiceEntry.parentVoiceEntry.IsGrace && !voiceEntry.parentVoiceEntry.GraceAfterMainNote) {
                         continue;
                     }
                 }

+ 9 - 0
src/MusicalScore/VoiceData/VoiceEntry.ts

@@ -29,6 +29,7 @@ export class VoiceEntry {
         this.parentVoice = parentVoice;
         this.parentSourceStaffEntry = parentSourceStaffEntry;
         this.isGrace = isGrace;
+        this.graceAfterMainNote = false;
         this.graceNoteSlash = graceNoteSlash;
         this.graceSlur = graceSlur;
     }
@@ -38,6 +39,8 @@ export class VoiceEntry {
     private timestamp: Fraction;
     private notes: Note[] = [];
     private isGrace: boolean;
+    /** States whether the grace notes come after a main note (at end of measure). */
+    private graceAfterMainNote: boolean;
     private graceNoteSlash: boolean;
     private graceSlur: boolean; // TODO grace slur system could be refined to be non-binary
     private articulations: ArticulationEnum[] = [];
@@ -69,6 +72,12 @@ export class VoiceEntry {
     public set IsGrace(value: boolean) {
         this.isGrace = value;
     }
+    public get GraceAfterMainNote(): boolean {
+        return this.graceAfterMainNote;
+    }
+    public set GraceAfterMainNote(value: boolean) {
+        this.graceAfterMainNote = value;
+    }
     public get GraceNoteSlash(): boolean {
         return this.graceNoteSlash;
     }