فهرست منبع

refactor: give each Note a reference to its SourceMeasure

add Note.NoteAsString() getter, useful for debugging
sschmid 4 سال پیش
والد
کامیت
6b2e130917

+ 1 - 1
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -2265,7 +2265,7 @@ export abstract class MusicSheetCalculator {
                                                           measure.parentSourceMeasure.CompleteNumberOfStaves),
                     staff);
                 const voiceEntry: VoiceEntry = new VoiceEntry(new Fraction(0, 1), staff.Voices[0], sourceStaffEntry);
-                const note: Note = new Note(voiceEntry, sourceStaffEntry, Fraction.createFromFraction(sourceMeasure.Duration), undefined);
+                const note: Note = new Note(voiceEntry, sourceStaffEntry, Fraction.createFromFraction(sourceMeasure.Duration), undefined, sourceMeasure);
                 note.PrintObject = this.rules.FillEmptyMeasuresWithWholeRest === FillEmptyMeasuresWithWholeRests.YesVisible;
                   // don't display whole rest that wasn't given in XML, only for layout/voice completion
                 voiceEntry.Notes.push(note);

+ 5 - 4
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -272,7 +272,7 @@ export class VoiceGenerator {
       if (openTieDict.hasOwnProperty(key)) {
         const tie: Tie = openTieDict[key];
         if (Fraction.plus(tie.StartNote.ParentStaffEntry.Timestamp, tie.Duration)
-          .lt(tie.StartNote.ParentStaffEntry.VerticalContainerParent.ParentMeasure.Duration)) {
+          .lt(tie.StartNote.SourceMeasure.Duration)) {
           delete openTieDict[key];
         }
       }
@@ -440,10 +440,11 @@ export class VoiceGenerator {
 
     if (stringNumber < 0 || fretNumber < 0) {
       // create normal Note
-      note = new Note(this.currentVoiceEntry, this.currentStaffEntry, noteLength, pitch);
+      note = new Note(this.currentVoiceEntry, this.currentStaffEntry, noteLength, pitch, this.currentMeasure);
     } else {
       // create TabNote
-      note = new TabNote(this.currentVoiceEntry, this.currentStaffEntry, noteLength, pitch, stringNumber, fretNumber, bends, vibratoStrokes);
+      note = new TabNote(this.currentVoiceEntry, this.currentStaffEntry, noteLength, pitch, this.currentMeasure,
+                         stringNumber, fretNumber, bends, vibratoStrokes);
     }
 
     note.TypeLength = typeDuration;
@@ -488,7 +489,7 @@ export class VoiceGenerator {
         const noteStep: NoteEnum = NoteEnum[displayStep.value.toUpperCase()];
         pitch = new Pitch(noteStep, parseInt(octave.value, 10), AccidentalEnum.NONE);
     }
-    const restNote: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, restFraction, pitch, true);
+    const restNote: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, restFraction, pitch, this.currentMeasure, true);
     restNote.NoteTypeXml = noteTypeXml;
     restNote.PrintObject = printObject;
     restNote.IsCueNote = isCueNote;

+ 12 - 4
src/MusicalScore/VoiceData/Note.ts

@@ -11,17 +11,19 @@ import {NoteState} from "../Graphical/DrawingEnums";
 import {Notehead} from "./Notehead";
 import {Arpeggio} from "./Arpeggio";
 import {NoteType} from "./NoteType";
+import { SourceMeasure } from "./SourceMeasure";
 
 /**
  * Represents a single pitch with a duration (length)
  */
 export class Note {
 
-    constructor(voiceEntry: VoiceEntry, parentStaffEntry: SourceStaffEntry, length: Fraction, pitch: Pitch, isRest?: boolean) {
+    constructor(voiceEntry: VoiceEntry, parentStaffEntry: SourceStaffEntry, length: Fraction, pitch: Pitch, sourceMeasure: SourceMeasure, isRest?: boolean) {
         this.voiceEntry = voiceEntry;
         this.parentStaffEntry = parentStaffEntry;
         this.length = length;
         this.pitch = pitch;
+        this.sourceMeasure = sourceMeasure;
         this.isRestFlag = isRest ?? false;
         if (pitch) {
             this.halfTone = pitch.getHalfTone();
@@ -38,6 +40,7 @@ export class Note {
     private voiceEntry: VoiceEntry;
     private parentStaffEntry: SourceStaffEntry;
     private length: Fraction;
+    private sourceMeasure: SourceMeasure;
     /** The length/duration given in the <type> tag. different from length for tuplets/tremolos. */
     private typeLength: Fraction;
     /** The NoteType given in the XML, e.g. quarter, which can be a normal quarter or tuplet quarter -> can have different length/fraction */
@@ -49,6 +52,9 @@ export class Note {
      * The untransposed (!!!) source data.
      */
     private pitch: Pitch;
+    public get NoteAsString(): string {
+        return this.pitch.toString();
+    }
     private beam: Beam;
     private tuplet: Tuplet;
     private tie: Tie;
@@ -104,6 +110,9 @@ export class Note {
     public set Length(value: Fraction) {
         this.length = value;
     }
+    public get SourceMeasure(): SourceMeasure {
+        return this.sourceMeasure;
+    }
     public get TypeLength(): Fraction {
         return this.typeLength;
     }
@@ -224,10 +233,9 @@ export class Note {
     /** Note: May be dangerous to use if ParentStaffEntry.VerticalContainerParent etc is not set.
      * better calculate this directly when you have access to the note's measure.
      * whole rest: length = measure length. (4/4 in a 4/4 time signature, 3/4 in a 3/4 time signature, 1/4 in a 1/4 time signature, etc.)
-     * TODO give a Note a reference to its measure?
      */
     public isWholeRest(): boolean {
-        return this.isRest() && this.Length.RealValue === this.ParentStaffEntry.VerticalContainerParent.ParentMeasure.ActiveTimeSignature.RealValue;
+        return this.isRest() && this.Length.RealValue === this.sourceMeasure.ActiveTimeSignature.RealValue;
     }
 
     public ToString(): string {
@@ -240,7 +248,7 @@ export class Note {
     public getAbsoluteTimestamp(): Fraction {
         return Fraction.plus(
             this.voiceEntry.Timestamp,
-            this.parentStaffEntry.VerticalContainerParent.ParentMeasure.AbsoluteTimestamp
+            this.sourceMeasure.AbsoluteTimestamp
         );
     }
     public checkForDoubleSlur(slur: Slur): boolean {

+ 3 - 2
src/MusicalScore/VoiceData/TabNote.ts

@@ -3,12 +3,13 @@ import { Fraction } from "../../Common/DataObjects/Fraction";
 import { VoiceEntry } from "./VoiceEntry";
 import { SourceStaffEntry } from "./SourceStaffEntry";
 import { Pitch } from "../../Common/DataObjects/Pitch";
+import { SourceMeasure } from "./SourceMeasure";
 
 export class TabNote extends Note {
-    constructor(voiceEntry: VoiceEntry, parentStaffEntry: SourceStaffEntry, length: Fraction, pitch: Pitch,
+    constructor(voiceEntry: VoiceEntry, parentStaffEntry: SourceStaffEntry, length: Fraction, pitch: Pitch, sourceMeasure: SourceMeasure,
                 stringNumber: number, fretNumber: number, bendArray: { bendalter: number, direction: string }[],
                 vibratoStroke: boolean) {
-        super(voiceEntry, parentStaffEntry, length, pitch);
+        super(voiceEntry, parentStaffEntry, length, pitch, sourceMeasure);
         this.stringNumber = stringNumber;
         this.fretNumber = fretNumber;
         this.bendArray = bendArray;

+ 15 - 14
src/MusicalScore/VoiceData/VoiceEntry.ts

@@ -11,6 +11,7 @@ import {OrnamentEnum} from "./OrnamentContainer";
 import {AccidentalEnum} from "../../Common/DataObjects/Pitch";
 import { Dictionary } from "typescript-collections";
 import {Arpeggio} from "./Arpeggio";
+import { SourceMeasure } from "./SourceMeasure";
 
 /**
  * A [[VoiceEntry]] contains the notes in a voice at a timestamp.
@@ -247,7 +248,7 @@ export class VoiceEntry {
                     if ((i % 2) === 0) {
                         this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                     } else {
-                        this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, higherPitch, alteration, voiceEntries);
+                        this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, baseNote.SourceMeasure, higherPitch, alteration, voiceEntries);
                     }
                 }
                 break;
@@ -259,13 +260,13 @@ export class VoiceEntry {
                 const higherPitch: Pitch = baseNote.Pitch.getTransposedPitch(1);
                 const higherAlteration: AccidentalEnum = activeKey.getAlterationForPitch(higherPitch);
                 this.createAlteratedVoiceEntry(
-                    currentTimestamp, length, baseVoice, higherPitch, higherAlteration, voiceEntries
+                    currentTimestamp, length, baseVoice, baseNote.SourceMeasure, higherPitch, higherAlteration, voiceEntries
                 );
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp.Add(length);
                 this.createAlteratedVoiceEntry(
-                    currentTimestamp, length, baseVoice, lowerPitch, lowerAlteration, voiceEntries
+                    currentTimestamp, length, baseVoice, baseNote.SourceMeasure, lowerPitch, lowerAlteration, voiceEntries
                 );
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
@@ -278,13 +279,13 @@ export class VoiceEntry {
                 const higherPitch: Pitch = baseNote.Pitch.getTransposedPitch(1);
                 const higherAlteration: AccidentalEnum = activeKey.getAlterationForPitch(higherPitch);
                 this.createAlteratedVoiceEntry(
-                    currentTimestamp, length, baseVoice, lowerPitch, lowerAlteration, voiceEntries
+                    currentTimestamp, length, baseVoice, baseNote.SourceMeasure, lowerPitch, lowerAlteration, voiceEntries
                 );
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp.Add(length);
                 this.createAlteratedVoiceEntry(
-                    currentTimestamp, length, baseVoice, higherPitch, higherAlteration, voiceEntries
+                    currentTimestamp, length, baseVoice, baseNote.SourceMeasure, higherPitch, higherAlteration, voiceEntries
                 );
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
@@ -299,11 +300,11 @@ export class VoiceEntry {
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp = Fraction.plus(baseTimestamp, length);
                 length.Denominator = baselength.Denominator * 8;
-                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, higherPitch, higherAlteration, voiceEntries);
+                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, baseNote.SourceMeasure, higherPitch, higherAlteration, voiceEntries);
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp.Add(length);
-                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, lowerPitch, lowerAlteration, voiceEntries);
+                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, baseNote.SourceMeasure, lowerPitch, lowerAlteration, voiceEntries);
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 break;
@@ -317,11 +318,11 @@ export class VoiceEntry {
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp = Fraction.plus(baseTimestamp, length);
                 length.Denominator = baselength.Denominator * 8;
-                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, lowerPitch, lowerAlteration, voiceEntries);
+                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, baseNote.SourceMeasure, lowerPitch, lowerAlteration, voiceEntries);
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp.Add(length);
-                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, higherPitch, higherAlteration, voiceEntries);
+                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, baseNote.SourceMeasure, higherPitch, higherAlteration, voiceEntries);
                 currentTimestamp.Add(length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 break;
@@ -332,7 +333,7 @@ export class VoiceEntry {
                 const alteration: AccidentalEnum = activeKey.getAlterationForPitch(higherPitch);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp.Add(length);
-                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, higherPitch, alteration, voiceEntries);
+                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, baseNote.SourceMeasure, higherPitch, alteration, voiceEntries);
                 length.Denominator = baselength.Denominator * 2;
                 currentTimestamp = Fraction.plus(baseTimestamp, length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
@@ -344,7 +345,7 @@ export class VoiceEntry {
                 const alteration: AccidentalEnum = activeKey.getAlterationForPitch(lowerPitch);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
                 currentTimestamp.Add(length);
-                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, lowerPitch, alteration, voiceEntries);
+                this.createAlteratedVoiceEntry(currentTimestamp, length, baseVoice, baseNote.SourceMeasure, lowerPitch, alteration, voiceEntries);
                 length.Denominator = baselength.Denominator * 2;
                 currentTimestamp = Fraction.plus(baseTimestamp, length);
                 this.createBaseVoiceEntry(currentTimestamp, length, baseVoice, baseNote, voiceEntries);
@@ -360,17 +361,17 @@ export class VoiceEntry {
     ): void {
         const voiceEntry: VoiceEntry = new VoiceEntry(currentTimestamp, baseVoice, baseNote.ParentStaffEntry);
         const pitch: Pitch = new Pitch(baseNote.Pitch.FundamentalNote, baseNote.Pitch.Octave, baseNote.Pitch.Accidental);
-        const note: Note = new Note(voiceEntry, undefined, length, pitch);
+        const note: Note = new Note(voiceEntry, undefined, length, pitch, baseNote.SourceMeasure);
         voiceEntry.Notes.push(note);
         voiceEntries.push(voiceEntry);
     }
     private createAlteratedVoiceEntry(
-        currentTimestamp: Fraction, length: Fraction, baseVoice: Voice, higherPitch: Pitch,
+        currentTimestamp: Fraction, length: Fraction, baseVoice: Voice, sourceMeasure: SourceMeasure, higherPitch: Pitch,
         alteration: AccidentalEnum, voiceEntries: VoiceEntry[]
     ): void {
         const voiceEntry: VoiceEntry = new VoiceEntry(currentTimestamp, baseVoice, undefined);
         const pitch: Pitch = new Pitch(higherPitch.FundamentalNote, higherPitch.Octave, alteration);
-        const note: Note = new Note(voiceEntry, undefined, length, pitch);
+        const note: Note = new Note(voiceEntry, undefined, length, pitch, sourceMeasure);
         voiceEntry.Notes.push(note);
         voiceEntries.push(voiceEntry);
     }

+ 2 - 1
test/Common/OSMD/OSMD_Test.ts

@@ -359,7 +359,8 @@ describe("OpenSheetMusicDisplay Main Export", () => {
                     voiceEntry,
                     voiceEntry.ParentSourceStaffEntry,
                     new Fraction(1),
-                    new Pitch(11, 2, AccidentalEnum.NATURAL));
+                    new Pitch(11, 2, AccidentalEnum.NATURAL),
+                    voiceEntry.ParentSourceStaffEntry.VerticalContainerParent.ParentMeasure);
                     // note: if the pitch is such that the voice entry frequencies aren't ordered correctly,
                     // Vexflow will complain about unsorted pitches. see below
                 voiceEntry.Notes.push(newNote);