Explorar el Código

Merge branch 'feature/TieRefactoring' into develop

Matthias Uiberacker hace 7 años
padre
commit
9946a61153

+ 12 - 0
src/Common/DataObjects/Fraction.ts

@@ -170,6 +170,12 @@ export class Fraction {
   //   this.setRealValue();
   // }
 
+  /**
+   * Adds a Fraction to this Fraction.
+   * Attention: This changes the already existing Fraction, which might be referenced elsewhere!
+   * Use Fraction.plus() for creating a new Fraction object being the sum of two Fractions.
+   * @param fraction the Fraction to add.
+   */
   public Add(fraction: Fraction): void {
     // normally should check if denominator or fraction.denominator is 0 but in our case
     // a zero denominator doesn't make sense
@@ -181,6 +187,12 @@ export class Fraction {
     this.setRealValue();
   }
 
+  /**
+   * Subtracts a Fraction from this Fraction.
+   * Attention: This changes the already existing Fraction, which might be referenced elsewhere!
+   * Use Fraction.minus() for creating a new Fraction object being the difference of two Fractions.
+   * @param fraction the Fraction to subtract.
+   */
   public Sub(fraction: Fraction): void {
     // normally should check if denominator or fraction.denominator is 0 but in our case
     // a zero denominator doesn't make sense

+ 1 - 5
src/MusicalScore/Graphical/GraphicalNote.ts

@@ -21,11 +21,7 @@ export class GraphicalNote extends GraphicalObject {
         if (graphicalNoteLength !== undefined) {
             this.graphicalNoteLength = graphicalNoteLength;
         } else {
-            if (note.NoteTie !== undefined) {
-                this.graphicalNoteLength = note.calculateNoteLengthWithoutTie();
-            } else {
-                this.graphicalNoteLength = note.Length;
-            }
+            this.graphicalNoteLength = note.Length;
         }
 
         this.numberOfDots = this.calculateNumberOfNeededDots(this.graphicalNoteLength);

+ 14 - 149
src/MusicalScore/Graphical/MusicSheetCalculator.ts

@@ -49,7 +49,6 @@ import {Staff} from "../VoiceData/Staff";
 import {OctaveShift} from "../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
 import {Logging} from "../../Common/Logging";
 import Dictionary from "typescript-collections/dist/lib/Dictionary";
-import {CollectionUtil} from "../../Util/CollectionUtil";
 import {GraphicalLyricEntry} from "./GraphicalLyricEntry";
 import {GraphicalLyricWord} from "./GraphicalLyricWord";
 import {GraphicalLine} from "./GraphicalLine";
@@ -89,21 +88,6 @@ export abstract class MusicSheetCalculator {
         return this.graphicalMusicSheet.LeadSheet;
     }
 
-    private static addTieToTieTimestampsDict(tieTimestampListDict: Dictionary<Tie, Fraction[]>, note: Note): void {
-        note.NoteTie.initializeBoolList();
-        const tieTimestampList: Fraction[] = [];
-        for (let m: number = 0; m < note.NoteTie.Fractions.length; m++) {
-            let musicTimestamp: Fraction;
-            if (m === 0) {
-                musicTimestamp = Fraction.plus(note.calculateNoteLengthWithoutTie(), note.getAbsoluteTimestamp());
-            } else {
-                musicTimestamp = Fraction.plus(tieTimestampList[m - 1], note.NoteTie.Fractions[m - 1]);
-            }
-            tieTimestampList.push(musicTimestamp);
-        }
-        tieTimestampListDict.setValue(note.NoteTie, tieTimestampList);
-    }
-
     private static setMeasuresMinStaffEntriesWidth(measures: StaffMeasure[], minimumStaffEntriesWidth: number): void {
         for (let idx: number = 0, len: number = measures.length; idx < len; ++idx) {
             const measure: StaffMeasure = measures[idx];
@@ -119,7 +103,7 @@ export abstract class MusicSheetCalculator {
     }
 
     /**
-     * Build the 2D [[GraphicalMeasure]] ist needed for the [[MusicSheetCalculator]].
+     * Build the 2D [[GraphicalMeasure]] list needed for the [[MusicSheetCalculator]].
      * Internally it creates [[GraphicalMeasure]]s, [[GraphicalStaffEntry]]'s and [[GraphicalNote]]s.
      */
     public prepareGraphicalMusicSheet(): void {
@@ -152,10 +136,7 @@ export abstract class MusicSheetCalculator {
         const openOctaveShifts: OctaveShiftParams[] = [];
 
         // TieList - timestampsArray
-        const tieTimestampListDictList: Dictionary<Tie, Fraction[]>[] = [];
         for (let i: number = 0; i < completeNumberOfStaves; i++) {
-            const tieTimestampListDict: Dictionary<Tie, Fraction[]> = new Dictionary<Tie, Fraction[]>();
-            tieTimestampListDictList.push(tieTimestampListDict);
             openOctaveShifts.push(undefined);
         }
 
@@ -166,7 +147,6 @@ export abstract class MusicSheetCalculator {
                 sourceMeasure,
                 accidentalCalculators,
                 lyricWords,
-                tieTimestampListDictList,
                 openOctaveShifts,
                 activeClefs
             );
@@ -925,7 +905,7 @@ export abstract class MusicSheetCalculator {
 
     protected handleVoiceEntry(voiceEntry: VoiceEntry, graphicalStaffEntry: GraphicalStaffEntry,
                                accidentalCalculator: AccidentalCalculator, openLyricWords: LyricWord[],
-                               tieTimestampListDict: Dictionary<Tie, Fraction[]>, activeClef: ClefInstruction,
+                               activeClef: ClefInstruction,
                                openTuplets: Tuplet[], openBeams: Beam[],
                                octaveShiftValue: OctaveEnum, grace: boolean = false, linkedNotes: Note[] = undefined,
                                sourceStaffEntry: SourceStaffEntry = undefined): OctaveEnum {
@@ -942,9 +922,6 @@ export abstract class MusicSheetCalculator {
             } else {
                 graphicalNote = MusicSheetCalculator.symbolFactory.createNote(note, gve, activeClef, octaveShiftValue, undefined);
             }
-            if (note.NoteTie !== undefined) {
-                MusicSheetCalculator.addTieToTieTimestampsDict(tieTimestampListDict, note);
-            }
             if (note.Pitch !== undefined) {
                 this.checkNoteForAccidental(graphicalNote, accidentalCalculator, activeClef, octaveShiftValue, grace);
             }
@@ -978,7 +955,6 @@ export abstract class MusicSheetCalculator {
     protected handleVoiceEntryGraceNotes(graceEntries: VoiceEntry[], graphicalGraceEntries: GraphicalStaffEntry[], graphicalStaffEntry: GraphicalStaffEntry,
                                          accidentalCalculator: AccidentalCalculator, activeClef: ClefInstruction,
                                          octaveShiftValue: OctaveEnum, lyricWords: LyricWord[],
-                                         tieTimestampListDict: Dictionary<Tie, Fraction[]>,
                                          tuplets: Tuplet[], beams: Beam[]): void {
         if (graceEntries !== undefined) {
             for (let idx: number = 0, len: number = graceEntries.length; idx < len; ++idx) {
@@ -990,82 +966,13 @@ export abstract class MusicSheetCalculator {
                 graphicalGraceEntries.push(graceStaffEntry);
                 this.handleVoiceEntry(
                     graceVoiceEntry, graceStaffEntry, accidentalCalculator, lyricWords,
-                    tieTimestampListDict, activeClef, tuplets,
+                    activeClef, tuplets,
                     beams, octaveShiftValue, true
                 );
             }
         }
     }
 
-    protected handleOpenTies(measure: StaffMeasure, beams: Beam[], tieTimestampListDict: Dictionary<Tie, Fraction[]>,
-                             activeClef: ClefInstruction, octaveShiftParams: OctaveShiftParams): void {
-        CollectionUtil.removeDictElementIfTrue( this, tieTimestampListDict,
-                                                function (thisPointer: MusicSheetCalculator, openTie: Tie, tieTimestamps: Fraction[]): boolean {
-            // for (let m: number = tieTimestampListDict.size() - 1; m >= 0; m--) {
-            //     let keyValuePair: KeyValuePair<Tie, Fraction[]> = tieTimestampListDict.ElementAt(m);
-            //     let openTie: Tie = keyValuePair.Key;
-            //    let tieTimestamps: Fraction[] = keyValuePair.Value;
-            let absoluteTimestamp: Fraction = undefined;
-
-            let removeTie: boolean = false;
-            for (let k: number = 0; k < tieTimestamps.length; k++) {
-                if (!openTie.NoteHasBeenCreated[k]) {
-                    absoluteTimestamp = tieTimestamps[k];
-                    if (Fraction.plus(measure.parentSourceMeasure.AbsoluteTimestamp, measure.parentSourceMeasure.Duration).lte(absoluteTimestamp)) {
-                        continue;
-                    }
-                    let graphicalStaffEntry: GraphicalStaffEntry = undefined;
-                    if (absoluteTimestamp !== undefined) {
-                        for (let idx: number = 0, len: number = measure.staffEntries.length; idx < len; ++idx) {
-                            const gse: GraphicalStaffEntry = measure.staffEntries[idx];
-                            if (gse.getAbsoluteTimestamp().Equals(absoluteTimestamp)) {
-                                graphicalStaffEntry = gse;
-                                break;
-                            }
-                        }
-                        if (graphicalStaffEntry === undefined) {
-                            graphicalStaffEntry = thisPointer.createStaffEntryForTieNote(measure, absoluteTimestamp, openTie);
-                        }
-                    }
-                    if (graphicalStaffEntry !== undefined) {
-                        let octaveShiftValue: OctaveEnum = OctaveEnum.NONE;
-                        if (octaveShiftParams !== undefined) {
-                            if (octaveShiftParams.getAbsoluteStartTimestamp.lte(graphicalStaffEntry.getAbsoluteTimestamp()) &&
-                                graphicalStaffEntry.getAbsoluteTimestamp().lte(octaveShiftParams.getAbsoluteEndTimestamp)) {
-                                octaveShiftValue = octaveShiftParams.getOpenOctaveShift.Type;
-                            }
-                        }
-                        const isLastTieNote: boolean = k === tieTimestamps.length - 1;
-                        const tieFraction: Fraction = openTie.Fractions[k];
-                        const gve: GraphicalVoiceEntry =
-                            graphicalStaffEntry.findOrCreateGraphicalVoiceEntry(openTie.Start.ParentVoiceEntry);
-
-                        // GraphicalNote points to tieStartNote, but must get the correct Length (eg the correct Fraction of tieStartNote's Length)
-                        const tiedGraphicalNote: GraphicalNote = MusicSheetCalculator.symbolFactory.createNote( openTie.Start, gve, activeClef,
-                                                                                                                octaveShiftValue, tieFraction);
-
-                        graphicalStaffEntry.addGraphicalNoteToListAtCorrectYPosition(gve, tiedGraphicalNote);
-
-                        thisPointer.handleTiedGraphicalNote(tiedGraphicalNote, beams, activeClef, octaveShiftValue, graphicalStaffEntry, tieFraction,
-                                                            openTie, isLastTieNote);
-
-                        const tieStartNote: Note = openTie.Start;
-                        if (isLastTieNote && tieStartNote.ParentVoiceEntry.Articulations.length === 1 &&
-                            tieStartNote.ParentVoiceEntry.Articulations[0] === ArticulationEnum.fermata) {
-                                MusicSheetCalculator.symbolFactory.addFermataAtTiedEndNote(tieStartNote, graphicalStaffEntry);
-                        }
-                        openTie.NoteHasBeenCreated[k] = true;
-                        if (openTie.allGraphicalNotesHaveBeenCreated()) {
-                            removeTie = true;
-                            //tieTimestampListDict.remove(openTie);
-                        }
-                    }
-                }
-            }
-            return removeTie;
-        });
-    }
-
     protected resetYPositionForLeadSheet(psi: BoundingBox): void {
         if (this.leadSheet) {
             psi.RelativePosition = new PointF2D(psi.RelativePosition.x, 0.0);
@@ -1320,26 +1227,13 @@ export abstract class MusicSheetCalculator {
 
     private handleTie(tie: Tie, startGraphicalStaffEntry: GraphicalStaffEntry, staffIndex: number, measureIndex: number): void {
         let startGse: GraphicalStaffEntry = startGraphicalStaffEntry;
+        let startNote: GraphicalNote = startGse.findEndTieGraphicalNoteFromNote(tie.StartNote);
         let endGse: GraphicalStaffEntry = undefined;
-        let startNote: GraphicalNote = undefined;
         let endNote: GraphicalNote = undefined;
-        for (let i: number = 0; i < tie.Fractions.length; i++) {
-            let verticalGraphicalStaffEntryContainer: VerticalGraphicalStaffEntryContainer;
-            let endTimestamp: Fraction;
-            const startContainerIndex: number = startGraphicalStaffEntry.parentVerticalContainer.Index;
-            if (i === 0) {
-                endTimestamp = Fraction.plus(startGraphicalStaffEntry.getAbsoluteTimestamp(), tie.Start.calculateNoteLengthWithoutTie());
-            } else {
-                endTimestamp = Fraction.plus(startGse.getAbsoluteTimestamp(), tie.Fractions[i - 1]);
-            }
-            verticalGraphicalStaffEntryContainer = this.graphicalMusicSheet.GetVerticalContainerFromTimestamp(endTimestamp, startContainerIndex + 1);
-            if (verticalGraphicalStaffEntryContainer !== undefined) {
-                endGse = verticalGraphicalStaffEntryContainer.StaffEntries[staffIndex];
-                startNote = startGse.findEndTieGraphicalNoteFromNote(tie.Start);
-                if (endGse !== undefined) {
-                    endNote = endGse.findEndTieGraphicalNoteFromNote(tie.Start);
-                }
-            }
+        for (let i: number = 1; i < tie.Notes.length; i++) {
+            startNote = startGse.findEndTieGraphicalNoteFromNote(tie.Notes[i - 1]);
+            endGse = this.graphicalMusicSheet.GetGraphicalFromSourceStaffEntry(tie.Notes[i].ParentStaffEntry);
+            endNote = endGse.findEndTieGraphicalNoteFromNote(tie.Notes[i]);
             if (startNote !== undefined && endNote !== undefined && endGse !== undefined) {
                 const graphicalTie: GraphicalTie = this.createGraphicalTie(tie, startGse, endGse, startNote, endNote);
                 startGse.GraphicalTies.push(graphicalTie);
@@ -1347,13 +1241,7 @@ export abstract class MusicSheetCalculator {
                     this.staffEntriesWithGraphicalTies.push(startGse);
                 }
             }
-            if (endGse !== undefined) {
-                if (endGse.parentMeasure !== startGse.parentMeasure) {
-                    measureIndex++;
-                }
-                startGse = endGse;
-                endGse = this.graphicalMusicSheet.findNextGraphicalStaffEntry(staffIndex, measureIndex, startGse);
-            }
+            startGse = endGse;
         }
     }
 
@@ -1404,7 +1292,6 @@ export abstract class MusicSheetCalculator {
 
     private createGraphicalMeasuresForSourceMeasure(sourceMeasure: SourceMeasure, accidentalCalculators: AccidentalCalculator[],
                                                     openLyricWords: LyricWord[],
-                                                    tieTimestampListDictList: Dictionary<Tie, Fraction[]>[],
                                                     openOctaveShifts: OctaveShiftParams[], activeClefs: ClefInstruction[]): StaffMeasure[] {
         this.initStaffMeasuresCreation();
         const verticalMeasureList: StaffMeasure[] = [];
@@ -1413,7 +1300,7 @@ export abstract class MusicSheetCalculator {
         const staffEntryLinks: StaffEntryLink[] = [];
         for (let staffIndex: number = 0; staffIndex < sourceMeasure.CompleteNumberOfStaves; staffIndex++) {
             const measure: StaffMeasure = this.createGraphicalMeasure(
-                sourceMeasure, tieTimestampListDictList[staffIndex], openTuplets, openBeams,
+                sourceMeasure, openTuplets, openBeams,
                 accidentalCalculators[staffIndex], activeClefs, openOctaveShifts, openLyricWords, staffIndex, staffEntryLinks
             );
             this.staffMeasureCreatedCalculations(measure);
@@ -1423,7 +1310,7 @@ export abstract class MusicSheetCalculator {
         return verticalMeasureList;
     }
 
-    private createGraphicalMeasure(sourceMeasure: SourceMeasure, tieTimestampListDict: Dictionary<Tie, Fraction[]>, openTuplets: Tuplet[], openBeams: Beam[],
+    private createGraphicalMeasure(sourceMeasure: SourceMeasure, openTuplets: Tuplet[], openBeams: Beam[],
                                    accidentalCalculator: AccidentalCalculator, activeClefs: ClefInstruction[],
                                    openOctaveShifts: OctaveShiftParams[], openLyricWords: LyricWord[], staffIndex: number,
                                    staffEntryLinks: StaffEntryLink[]): StaffMeasure {
@@ -1489,12 +1376,11 @@ export abstract class MusicSheetCalculator {
                     this.handleVoiceEntryGraceNotes(
                         voiceEntry.graceVoiceEntriesBefore, graphicalStaffEntry.graceStaffEntriesBefore, graphicalStaffEntry,
                         accidentalCalculator, activeClefs[staffIndex], octaveShiftValue, openLyricWords,
-                        tieTimestampListDict, openTuplets, openBeams
+                        openTuplets, openBeams
                     );
                     octaveShiftValue = this.handleVoiceEntry(
                         voiceEntry, graphicalStaffEntry,
                         accidentalCalculator, openLyricWords,
-                        tieTimestampListDict,
                         activeClefs[staffIndex], openTuplets,
                         openBeams, octaveShiftValue, false, linkedNotes,
                         sourceStaffEntry
@@ -1502,7 +1388,7 @@ export abstract class MusicSheetCalculator {
                     this.handleVoiceEntryGraceNotes(
                         voiceEntry.graceVoiceEntriesAfter, graphicalStaffEntry.graceStaffEntriesAfter, graphicalStaffEntry,
                         accidentalCalculator, activeClefs[staffIndex], octaveShiftValue, openLyricWords,
-                        tieTimestampListDict, openTuplets, openBeams
+                        openTuplets, openBeams
                     );
                 }
                 if (sourceStaffEntry.Instructions.length > 0) {
@@ -1518,12 +1404,7 @@ export abstract class MusicSheetCalculator {
                 }
             }
         }
-        if (tieTimestampListDict.size() > 0) {
-            this.handleOpenTies(
-                measure, openBeams,
-                tieTimestampListDict, activeClefs[staffIndex], openOctaveShifts[staffIndex]
-            );
-        }
+
         accidentalCalculator.doCalculationsAtEndOfMeasure();
         if (sourceMeasure.LastInstructionsStaffEntries[staffIndex] !== undefined) {
             const lastStaffEntry: SourceStaffEntry = sourceMeasure.LastInstructionsStaffEntries[staffIndex];
@@ -1573,9 +1454,6 @@ export abstract class MusicSheetCalculator {
             pitch = graphicalNote.Transpose(
                 accidentalCalculator.ActiveKeyInstruction, activeClef, transpose, octaveEnum
             );
-            if (graphicalNote.sourceNote.NoteTie !== undefined) {
-                graphicalNote.sourceNote.NoteTie.BaseNoteYPosition = graphicalNote.PositionAndShape.RelativePosition.y;
-            }
         }
         graphicalNote.sourceNote.halfTone = pitch.getHalfTone();
         let scalingFactor: number = 1.0;
@@ -1585,19 +1463,6 @@ export abstract class MusicSheetCalculator {
         accidentalCalculator.checkAccidental(graphicalNote, pitch, grace, scalingFactor);
     }
 
-    // needed to disable linter, as it doesn't recognize the existing usage of this method.
-    // ToDo: check if a newer version doesn't have the problem.
-    /* tslint:disable:no-unused-variable */
-    private createStaffEntryForTieNote(measure: StaffMeasure, absoluteTimestamp: Fraction, openTie: Tie): GraphicalStaffEntry {
-        /* tslint:enable:no-unused-variable */
-        let graphicalStaffEntry: GraphicalStaffEntry;
-        graphicalStaffEntry = MusicSheetCalculator.symbolFactory.createStaffEntry(openTie.Start.ParentStaffEntry, measure);
-        graphicalStaffEntry.relInMeasureTimestamp = Fraction.minus(absoluteTimestamp, measure.parentSourceMeasure.AbsoluteTimestamp);
-        this.resetYPositionForLeadSheet(graphicalStaffEntry.PositionAndShape);
-        measure.addGraphicalStaffEntryAtTimestamp(graphicalStaffEntry);
-        return graphicalStaffEntry;
-    }
-
     private updateSkyBottomLines(): void {
         for (let idx: number = 0, len: number = this.graphicalMusicSheet.MusicPages.length; idx < len; ++idx) {
             const graphicalMusicPage: GraphicalMusicPage = this.graphicalMusicSheet.MusicPages[idx];

+ 14 - 5
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -220,35 +220,44 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
      */
   protected layoutGraphicalTie(tie: GraphicalTie, tieIsAtSystemBreak: boolean): void {
     const startNote: VexFlowGraphicalNote = (tie.StartNote as VexFlowGraphicalNote);
+    const endNote: VexFlowGraphicalNote = (tie.EndNote as VexFlowGraphicalNote);
+
     let vfStartNote: Vex.Flow.StaveNote = undefined;
+    let startNoteIndexInTie: number = 0;
     if (startNote !== undefined) {
       vfStartNote = startNote.vfnote[0];
+      startNoteIndexInTie = startNote.vfnote[1];
     }
 
-    const endNote: VexFlowGraphicalNote = (tie.EndNote as VexFlowGraphicalNote);
     let vfEndNote: Vex.Flow.StaveNote = undefined;
+    let endNoteIndexInTie: number = 0;
     if (endNote !== undefined) {
       vfEndNote = endNote.vfnote[0];
+      endNoteIndexInTie = endNote.vfnote[1];
     }
 
-
     if (tieIsAtSystemBreak) {
       // split tie into two ties:
       const vfTie1: Vex.Flow.StaveTie = new Vex.Flow.StaveTie({
-        first_note: vfStartNote,
+        first_indices: [startNoteIndexInTie],
+        first_note: vfStartNote
       });
       const measure1: VexFlowMeasure = (startNote.parentVoiceEntry.parentStaffEntry.parentMeasure as VexFlowMeasure);
       measure1.vfTies.push(vfTie1);
 
       const vfTie2: Vex.Flow.StaveTie = new Vex.Flow.StaveTie({
-        last_note: vfEndNote,
+        last_indices: [endNoteIndexInTie],
+        last_note: vfEndNote
       });
       const measure2: VexFlowMeasure = (endNote.parentVoiceEntry.parentStaffEntry.parentMeasure as VexFlowMeasure);
       measure2.vfTies.push(vfTie2);
     } else {
+      // normal case
       const vfTie: Vex.Flow.StaveTie = new Vex.Flow.StaveTie({
+        first_indices: [startNoteIndexInTie],
         first_note: vfStartNote,
-        last_note: vfEndNote,
+        last_indices: [endNoteIndexInTie],
+        last_note: vfEndNote
       });
       const measure: VexFlowMeasure = (endNote.parentVoiceEntry.parentStaffEntry.parentMeasure as VexFlowMeasure);
       measure.vfTies.push(vfTie);

+ 143 - 249
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -1,34 +1,29 @@
-import {Instrument} from "../Instrument";
-import {LinkedVoice} from "../VoiceData/LinkedVoice";
-import {Voice} from "../VoiceData/Voice";
-import {MusicSheet} from "../MusicSheet";
-import {VoiceEntry} from "../VoiceData/VoiceEntry";
-import {Note} from "../VoiceData/Note";
-import {SourceMeasure} from "../VoiceData/SourceMeasure";
-import {SourceStaffEntry} from "../VoiceData/SourceStaffEntry";
-import {Beam} from "../VoiceData/Beam";
-import {Tie} from "../VoiceData/Tie";
-import {Tuplet} from "../VoiceData/Tuplet";
-import {Fraction} from "../../Common/DataObjects/Fraction";
-//import {MusicSymbolModuleFactory} from "./InstrumentReader";
-import {IXmlElement} from "../../Common/FileIO/Xml";
-import {ITextTranslation} from "../Interfaces/ITextTranslation";
-import {ArticulationEnum} from "../VoiceData/VoiceEntry";
-import {Slur} from "../VoiceData/Expressions/ContinuousExpressions/Slur";
-import {LyricsEntry} from "../VoiceData/Lyrics/LyricsEntry";
-import {LyricsReader} from "../ScoreIO/MusicSymbolModules/LyricsReader";
-import {MusicSheetReadingException} from "../Exceptions";
-import {AccidentalEnum} from "../../Common/DataObjects/Pitch";
-import {NoteEnum} from "../../Common/DataObjects/Pitch";
-import {Staff} from "../VoiceData/Staff";
-import {StaffEntryLink} from "../VoiceData/StaffEntryLink";
-import {VerticalSourceStaffEntryContainer} from "../VoiceData/VerticalSourceStaffEntryContainer";
-import {Logging} from "../../Common/Logging";
-import {Pitch} from "../../Common/DataObjects/Pitch";
-import {IXmlAttribute} from "../../Common/FileIO/Xml";
-import {CollectionUtil} from "../../Util/CollectionUtil";
-import Dictionary from "typescript-collections/dist/lib/Dictionary";
-import {ArticulationReader} from "./MusicSymbolModules/ArticulationReader";
+import { Instrument } from "../Instrument";
+import { LinkedVoice } from "../VoiceData/LinkedVoice";
+import { Voice } from "../VoiceData/Voice";
+import { MusicSheet } from "../MusicSheet";
+import { VoiceEntry } from "../VoiceData/VoiceEntry";
+import { Note } from "../VoiceData/Note";
+import { SourceMeasure } from "../VoiceData/SourceMeasure";
+import { SourceStaffEntry } from "../VoiceData/SourceStaffEntry";
+import { Beam } from "../VoiceData/Beam";
+import { Tie } from "../VoiceData/Tie";
+import { Tuplet } from "../VoiceData/Tuplet";
+import { Fraction } from "../../Common/DataObjects/Fraction";
+import { IXmlElement } from "../../Common/FileIO/Xml";
+import { ITextTranslation } from "../Interfaces/ITextTranslation";
+import { LyricsReader } from "../ScoreIO/MusicSymbolModules/LyricsReader";
+import { MusicSheetReadingException } from "../Exceptions";
+import { AccidentalEnum } from "../../Common/DataObjects/Pitch";
+import { NoteEnum } from "../../Common/DataObjects/Pitch";
+import { Staff } from "../VoiceData/Staff";
+import { StaffEntryLink } from "../VoiceData/StaffEntryLink";
+import { VerticalSourceStaffEntryContainer } from "../VoiceData/VerticalSourceStaffEntryContainer";
+import { Logging } from "../../Common/Logging";
+import { Pitch } from "../../Common/DataObjects/Pitch";
+import { IXmlAttribute } from "../../Common/FileIO/Xml";
+import { CollectionUtil } from "../../Util/CollectionUtil";
+import { ArticulationReader } from "./MusicSymbolModules/ArticulationReader";
 
 /**
  * To be implemented
@@ -50,7 +45,7 @@ export class VoiceGenerator {
   }
 
   // private slurReader: SlurReader;
-    private lyricsReader: LyricsReader;
+  private lyricsReader: LyricsReader;
   private articulationReader: ArticulationReader;
   private musicSheet: MusicSheet;
   private voice: Voice;
@@ -121,8 +116,8 @@ export class VoiceGenerator {
         : this.addSingleNote(noteNode, noteDuration, graceNote, chord, guitarPro);
 
       if (this.lyricsReader !== undefined && noteNode.elements("lyric") !== undefined) {
-          this.lyricsReader.addLyricEntry(noteNode.elements("lyric"), this.currentVoiceEntry);
-          this.voice.Parent.HasLyrics = true;
+        this.lyricsReader.addLyricEntry(noteNode.elements("lyric"), this.currentVoiceEntry);
+        this.voice.Parent.HasLyrics = true;
       }
       let hasTupletCommand: boolean = false;
       const notationNode: IXmlElement = noteNode.element("notations");
@@ -156,8 +151,8 @@ export class VoiceGenerator {
         const openTieDict: { [_: number]: Tie; } = this.openTieDict;
         for (const key in openTieDict) {
           if (openTieDict.hasOwnProperty(key)) {
-                        const tie: Tie = openTieDict[key];
-                        if (Fraction.plus(tie.Start.ParentStaffEntry.Timestamp, tie.Start.Length).lt(this.currentStaffEntry.Timestamp)) {
+            const tie: Tie = openTieDict[key];
+            if (Fraction.plus(tie.StartNote.ParentStaffEntry.Timestamp, tie.Duration).lt(this.currentStaffEntry.Timestamp)) {
               delete openTieDict[key];
             }
           }
@@ -169,10 +164,10 @@ export class VoiceGenerator {
         this.handleTimeModificationNode(noteNode);
       }
     } catch (err) {
-            const errorMsg: string = ITextTranslation.translateText(
+      const errorMsg: string = ITextTranslation.translateText(
         "ReaderErrorMessages/NoteError", "Ignored erroneous Note."
       );
-            this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+      this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
     }
 
     return this.currentNote;
@@ -189,11 +184,11 @@ export class VoiceGenerator {
       && this.currentVoiceEntry.graceVoiceEntriesBefore !== undefined
       && this.currentVoiceEntry.graceVoiceEntriesBefore.length > 0
     ) {
-        const voice: Voice = this.currentVoiceEntry.ParentVoice;
-        const horizontalIndex: number = this.currentMeasure.VerticalSourceStaffEntryContainers.indexOf(this.currentStaffEntry.VerticalContainerParent);
-        const verticalIndex: number = this.currentStaffEntry.VerticalContainerParent.StaffEntries.indexOf(this.currentStaffEntry);
-        const previousStaffEntry: SourceStaffEntry = this.currentMeasure.getPreviousSourceStaffEntryFromIndex(verticalIndex, horizontalIndex);
-        if (previousStaffEntry !== undefined) {
+      const voice: Voice = this.currentVoiceEntry.ParentVoice;
+      const horizontalIndex: number = this.currentMeasure.VerticalSourceStaffEntryContainers.indexOf(this.currentStaffEntry.VerticalContainerParent);
+      const verticalIndex: number = this.currentStaffEntry.VerticalContainerParent.StaffEntries.indexOf(this.currentStaffEntry);
+      const previousStaffEntry: SourceStaffEntry = this.currentMeasure.getPreviousSourceStaffEntryFromIndex(verticalIndex, horizontalIndex);
+      if (previousStaffEntry !== undefined) {
         let previousVoiceEntry: VoiceEntry = undefined;
         for (let idx: number = 0, len: number = previousStaffEntry.VoiceEntries.length; idx < len; ++idx) {
           const voiceEntry: VoiceEntry = previousStaffEntry.VoiceEntries[idx];
@@ -245,12 +240,12 @@ export class VoiceGenerator {
   }
 
   public checkOpenTies(): void {
-    const openTieDict: {[key: number]: Tie} = this.openTieDict;
+    const openTieDict: { [key: number]: Tie } = this.openTieDict;
     for (const key in openTieDict) {
       if (openTieDict.hasOwnProperty(key)) {
-                const tie: Tie = openTieDict[key];
-                if (Fraction.plus(tie.Start.ParentStaffEntry.Timestamp, tie.Start.Length)
-            .lt(tie.Start.ParentStaffEntry.VerticalContainerParent.ParentMeasure.Duration)) {
+        const tie: Tie = openTieDict[key];
+        if (Fraction.plus(tie.StartNote.ParentStaffEntry.Timestamp, tie.Duration)
+          .lt(tie.StartNote.ParentStaffEntry.VerticalContainerParent.ParentMeasure.Duration)) {
           delete openTieDict[key];
         }
       }
@@ -298,10 +293,10 @@ export class VoiceGenerator {
       case "maxima":
         return new Fraction(8, 1);
       default: {
-                const errorMsg: string = ITextTranslation.translateText(
+        const errorMsg: string = ITextTranslation.translateText(
           "ReaderErrorMessages/NoteDurationError", "Invalid note duration."
         );
-                throw new MusicSheetReadingException(errorMsg);
+        throw new MusicSheetReadingException(errorMsg);
       }
     }
   }
@@ -353,21 +348,21 @@ export class VoiceGenerator {
               if (pitchElement.name === "step") {
                 noteStep = NoteEnum[pitchElement.value];
                 if (noteStep === undefined) {
-                    const errorMsg: string = ITextTranslation.translateText(
+                  const errorMsg: string = ITextTranslation.translateText(
                     "ReaderErrorMessages/NotePitchError",
                     "Invalid pitch while reading note."
                   );
-                    this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                    throw new MusicSheetReadingException(errorMsg, undefined);
+                  this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                  throw new MusicSheetReadingException(errorMsg, undefined);
                 }
               } else if (pitchElement.name === "alter") {
                 noteAlter = parseInt(pitchElement.value, 10);
                 if (isNaN(noteAlter)) {
-                                    const errorMsg: string = ITextTranslation.translateText(
+                  const errorMsg: string = ITextTranslation.translateText(
                     "ReaderErrorMessages/NoteAlterationError", "Invalid alteration while reading note."
                   );
-                                    this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                                    throw new MusicSheetReadingException(errorMsg, undefined);
+                  this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                  throw new MusicSheetReadingException(errorMsg, undefined);
                 }
 
               } else if (pitchElement.name === "octave") {
@@ -536,8 +531,8 @@ export class VoiceGenerator {
       const verticalIndex: number = beamLastNoteStaffEntry.VerticalContainerParent.StaffEntries.indexOf(beamLastNoteStaffEntry);
       if (horizontalIndex < this.currentMeasure.VerticalSourceStaffEntryContainers.length - 1) {
         const nextStaffEntry: SourceStaffEntry = this.currentMeasure
-                                                             .VerticalSourceStaffEntryContainers[horizontalIndex + 1]
-                                                             .StaffEntries[verticalIndex];
+          .VerticalSourceStaffEntryContainers[horizontalIndex + 1]
+          .StaffEntries[verticalIndex];
         if (nextStaffEntry !== undefined) {
           for (let idx: number = 0, len: number = nextStaffEntry.VoiceEntries.length; idx < len; ++idx) {
             const voiceEntry: VoiceEntry = nextStaffEntry.VoiceEntries[idx];
@@ -569,11 +564,11 @@ export class VoiceGenerator {
           note.Length = this.getNoteDurationFromType(type);
           note.Length.Numerator = 1;
         } catch (e) {
-                    const errorMsg: string = ITextTranslation.translateText(
+          const errorMsg: string = ITextTranslation.translateText(
             "ReaderErrorMessages/NoteDurationError", "Invalid note duration."
           );
-                    this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                    throw new MusicSheetReadingException(errorMsg, e);
+          this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+          throw new MusicSheetReadingException(errorMsg, e);
         }
 
       }
@@ -581,8 +576,8 @@ export class VoiceGenerator {
     const graceNode: IXmlElement = node.element("grace");
     if (graceNode !== undefined && graceNode.attributes()) {
       if (graceNode.attribute("slash")) {
-                const slash: string = graceNode.attribute("slash").value;
-                if (slash === "yes") {
+        const slash: string = graceNode.attribute("slash").value;
+        if (slash === "yes") {
           note.GraceNoteSlash = true;
         }
       }
@@ -627,10 +622,10 @@ export class VoiceGenerator {
       }
       const tupletNodeListArr: IXmlElement[] = tupletNodeList;
       for (let idx: number = 0, len: number = tupletNodeListArr.length; idx < len; ++idx) {
-                const tupletNode: IXmlElement = tupletNodeListArr[idx];
-                if (tupletNode !== undefined && tupletNode.attributes()) {
-                    const type: string = tupletNode.attribute("type").value;
-                    if (type === "start") {
+        const tupletNode: IXmlElement = tupletNodeListArr[idx];
+        if (tupletNode !== undefined && tupletNode.attributes()) {
+          const type: string = tupletNode.attribute("type").value;
+          if (type === "start") {
             let tupletNumber: number = 1;
             if (tupletNode.attribute("number")) {
               tupletNumber = parseInt(tupletNode.attribute("number").value, 10);
@@ -639,11 +634,11 @@ export class VoiceGenerator {
             if (timeModNode !== undefined) {
               tupletLabelNumber = parseInt(timeModNode.value, 10);
               if (isNaN(tupletLabelNumber)) {
-                                const errorMsg: string = ITextTranslation.translateText(
+                const errorMsg: string = ITextTranslation.translateText(
                   "ReaderErrorMessages/TupletNoteDurationError", "Invalid tuplet note duration."
                 );
-                                this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                                throw new MusicSheetReadingException(errorMsg, undefined);
+                this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+                throw new MusicSheetReadingException(errorMsg, undefined);
               }
 
             }
@@ -670,13 +665,13 @@ export class VoiceGenerator {
             }
             const tuplet: Tuplet = this.tupletDict[tupletNumber];
             if (tuplet !== undefined) {
-                            const subnotelist: Note[] = [];
-                            subnotelist.push(this.currentNote);
-                            tuplet.Notes.push(subnotelist);
-                            tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
-                            this.currentNote.NoteTuplet = tuplet;
-                            delete this.tupletDict[tupletNumber];
-                            if (Object.keys(this.tupletDict).length === 0) {
+              const subnotelist: Note[] = [];
+              subnotelist.push(this.currentNote);
+              tuplet.Notes.push(subnotelist);
+              tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
+              this.currentNote.NoteTuplet = tuplet;
+              delete this.tupletDict[tupletNumber];
+              if (Object.keys(this.tupletDict).length === 0) {
                 this.openTupletNumber = 0;
               } else if (Object.keys(this.tupletDict).length > 1) {
                 this.openTupletNumber--;
@@ -686,16 +681,16 @@ export class VoiceGenerator {
         }
       }
     } else if (tupletNodeList[0] !== undefined) {
-            const n: IXmlElement = tupletNodeList[0];
-            if (n.hasAttributes) {
-                const type: string = n.attribute("type").value;
-                let tupletnumber: number = 1;
-                if (n.attribute("number")) {
+      const n: IXmlElement = tupletNodeList[0];
+      if (n.hasAttributes) {
+        const type: string = n.attribute("type").value;
+        let tupletnumber: number = 1;
+        if (n.attribute("number")) {
           tupletnumber = parseInt(n.attribute("number").value, 10);
         }
-                const noTupletNumbering: boolean = isNaN(tupletnumber);
+        const noTupletNumbering: boolean = isNaN(tupletnumber);
 
-                if (type === "start") {
+        if (type === "start") {
           let tupletLabelNumber: number = 0;
           let timeModNode: IXmlElement = node.element("time-modification");
           if (timeModNode !== undefined) {
@@ -704,11 +699,11 @@ export class VoiceGenerator {
           if (timeModNode !== undefined) {
             tupletLabelNumber = parseInt(timeModNode.value, 10);
             if (isNaN(tupletLabelNumber)) {
-                            const errorMsg: string = ITextTranslation.translateText(
+              const errorMsg: string = ITextTranslation.translateText(
                 "ReaderErrorMessages/TupletNoteDurationError", "Invalid tuplet note duration."
               );
-                            this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                            throw new MusicSheetReadingException(errorMsg);
+              this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+              throw new MusicSheetReadingException(errorMsg);
             }
 
           }
@@ -732,17 +727,17 @@ export class VoiceGenerator {
           }
           const tuplet: Tuplet = this.tupletDict[this.openTupletNumber];
           if (tuplet !== undefined) {
-                        const subnotelist: Note[] = [];
-                        subnotelist.push(this.currentNote);
-                        tuplet.Notes.push(subnotelist);
-                        tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
-                        this.currentNote.NoteTuplet = tuplet;
-                        if (Object.keys(this.tupletDict).length === 0) {
+            const subnotelist: Note[] = [];
+            subnotelist.push(this.currentNote);
+            tuplet.Notes.push(subnotelist);
+            tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
+            this.currentNote.NoteTuplet = tuplet;
+            if (Object.keys(this.tupletDict).length === 0) {
               this.openTupletNumber = 0;
             } else if (Object.keys(this.tupletDict).length > 1) {
               this.openTupletNumber--;
             }
-                        delete this.tupletDict[tupletnumber];
+            delete this.tupletDict[tupletnumber];
           }
         }
       }
@@ -758,34 +753,34 @@ export class VoiceGenerator {
     if (this.tupletDict[this.openTupletNumber] !== undefined) {
       try {
         // Tuplet should already be created
-                const tuplet: Tuplet = this.tupletDict[this.openTupletNumber];
-                const notes: Note[] = CollectionUtil.last(tuplet.Notes);
-                const lastTupletVoiceEntry: VoiceEntry = notes[0].ParentVoiceEntry;
-                let noteList: Note[];
-                if (lastTupletVoiceEntry.Timestamp.Equals(this.currentVoiceEntry.Timestamp)) {
+        const tuplet: Tuplet = this.tupletDict[this.openTupletNumber];
+        const notes: Note[] = CollectionUtil.last(tuplet.Notes);
+        const lastTupletVoiceEntry: VoiceEntry = notes[0].ParentVoiceEntry;
+        let noteList: Note[];
+        if (lastTupletVoiceEntry.Timestamp.Equals(this.currentVoiceEntry.Timestamp)) {
           noteList = notes;
         } else {
           noteList = [];
           tuplet.Notes.push(noteList);
           tuplet.Fractions.push(this.getTupletNoteDurationFromType(noteNode));
         }
-                noteList.push(this.currentNote);
-                this.currentNote.NoteTuplet = tuplet;
+        noteList.push(this.currentNote);
+        this.currentNote.NoteTuplet = tuplet;
       } catch (ex) {
-                const errorMsg: string = ITextTranslation.translateText(
+        const errorMsg: string = ITextTranslation.translateText(
           "ReaderErrorMessages/TupletNumberError", "Invalid tuplet number."
         );
-                this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                throw ex;
+        this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+        throw ex;
       }
 
     } else if (this.currentVoiceEntry.Notes.length > 0) {
-            const firstNote: Note = this.currentVoiceEntry.Notes[0];
-            if (firstNote.NoteTuplet !== undefined) {
-                const tuplet: Tuplet = firstNote.NoteTuplet;
-                const notes: Note[] = CollectionUtil.last(tuplet.Notes);
-                notes.push(this.currentNote);
-                this.currentNote.NoteTuplet = tuplet;
+      const firstNote: Note = this.currentVoiceEntry.Notes[0];
+      if (firstNote.NoteTuplet !== undefined) {
+        const tuplet: Tuplet = firstNote.NoteTuplet;
+        const notes: Note[] = CollectionUtil.last(tuplet.Notes);
+        notes.push(this.currentNote);
+        this.currentNote.NoteTuplet = tuplet;
       }
     }
   }
@@ -793,144 +788,43 @@ export class VoiceGenerator {
   private addTie(tieNodeList: IXmlElement[], measureStartAbsoluteTimestamp: Fraction, maxTieNoteFraction: Fraction): void {
     if (tieNodeList !== undefined) {
       if (tieNodeList.length === 1) {
-                const tieNode: IXmlElement = tieNodeList[0];
-                if (tieNode !== undefined && tieNode.attributes()) {
-                    const type: string = tieNode.attribute("type").value;
-                    try {
+        const tieNode: IXmlElement = tieNodeList[0];
+        if (tieNode !== undefined && tieNode.attributes()) {
+          const type: string = tieNode.attribute("type").value;
+          try {
             if (type === "start") {
-                            const num: number = this.findCurrentNoteInTieDict(this.currentNote);
-                            if (num < 0) {
+              const num: number = this.findCurrentNoteInTieDict(this.currentNote);
+              if (num < 0) {
                 delete this.openTieDict[num];
               }
-                            const newTieNumber: number = this.getNextAvailableNumberForTie();
-                            const tie: Tie = new Tie(this.currentNote);
-                            this.openTieDict[newTieNumber] = tie;
-                            if (this.currentNote.NoteBeam !== undefined) {
-                if (this.currentNote.NoteBeam.Notes[0] === this.currentNote) {
-                  tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
-                } else {
-                  for (let idx: number = 0, len: number = this.currentNote.NoteBeam.Notes.length; idx < len; ++idx) {
-                                        const note: Note = this.currentNote.NoteBeam.Notes[idx];
-                                        if (note.NoteTie !== undefined && note.NoteTie !== tie && note.NoteTie.BeamStartTimestamp !== undefined) {
-                      tie.BeamStartTimestamp = note.NoteTie.BeamStartTimestamp;
-                      break;
-                    }
-                  }
-                  if (this.currentNote === CollectionUtil.last(this.currentNote.NoteBeam.Notes)) {
-                    tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
-                  }
-                }
-              }
+              const newTieNumber: number = this.getNextAvailableNumberForTie();
+              const tie: Tie = new Tie(this.currentNote);
+              this.openTieDict[newTieNumber] = tie;
             } else if (type === "stop") {
-                            const tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
-                            const tie: Tie = this.openTieDict[tieNumber];
-                            if (tie !== undefined) {
-                                const tieStartNote: Note = tie.Start;
-                                tieStartNote.NoteTie = tie;
-                                tieStartNote.Length.Add(this.currentNote.Length);
-                                tie.Fractions.push(this.currentNote.Length);
-                                if (maxTieNoteFraction.lt(Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length))) {
+              const tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
+              const tie: Tie = this.openTieDict[tieNumber];
+              if (tie !== undefined) {
+                tie.AddNote(this.currentNote);
+                if (maxTieNoteFraction.lt(Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length))) {
                   maxTieNoteFraction = Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length);
                 }
-                                const i: number = this.currentVoiceEntry.Notes.indexOf(this.currentNote);
-                                if (i !== -1) {
-                  this.currentVoiceEntry.Notes.splice(i, 1);
-                }
-                                if (
-                  this.currentVoiceEntry.Articulations.length === 1
-                  && this.currentVoiceEntry.Articulations[0] === ArticulationEnum.fermata
-                  && tieStartNote.ParentVoiceEntry.Articulations[ArticulationEnum.fermata] === undefined
-                ) {
-                  tieStartNote.ParentVoiceEntry.Articulations.push(ArticulationEnum.fermata);
-                }
-                                if (this.currentNote.NoteBeam !== undefined) {
-                                    const noteBeamIndex: number = this.currentNote.NoteBeam.Notes.indexOf(this.currentNote);
-                                    if (noteBeamIndex === 0 && tie.BeamStartTimestamp === undefined) {
-                    tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
-                  }
-                                    const noteBeam: Beam = this.currentNote.NoteBeam;
-                                    noteBeam.Notes[noteBeamIndex] = tieStartNote;
-                                    tie.TieBeam = noteBeam;
-                }
-                                if (this.currentNote.NoteTuplet !== undefined) {
-                                    const noteTupletIndex: number = this.currentNote.NoteTuplet.getNoteIndex(this.currentNote);
-                                    const index: number = this.currentNote.NoteTuplet.Notes[noteTupletIndex].indexOf(this.currentNote);
-                                    const noteTuplet: Tuplet = this.currentNote.NoteTuplet;
-                                    noteTuplet.Notes[noteTupletIndex][index] = tieStartNote;
-                                    tie.TieTuplet = noteTuplet;
-                }
-                                for (let idx: number = 0, len: number = this.currentNote.NoteSlurs.length; idx < len; ++idx) {
-                                    const slur: Slur = this.currentNote.NoteSlurs[idx];
-                                    if (slur.StartNote === this.currentNote) {
-                    slur.StartNote = tie.Start;
-                    slur.StartNote.NoteSlurs.push(slur);
-                  }
-                                    if (slur.EndNote === this.currentNote) {
-                    slur.EndNote = tie.Start;
-                    slur.EndNote.NoteSlurs.push(slur);
-                  }
-                }
-                                const lyricsEntries: Dictionary<number, LyricsEntry> = this.currentVoiceEntry.LyricsEntries;
-                                for (const lyricsEntry in lyricsEntries) {
-                  if (lyricsEntries.hasOwnProperty(lyricsEntry)) {
-                                        const val: LyricsEntry = this.currentVoiceEntry.LyricsEntries[lyricsEntry];
-                                        if (!tieStartNote.ParentVoiceEntry.LyricsEntries.hasOwnProperty(lyricsEntry)) {
-                      tieStartNote.ParentVoiceEntry.LyricsEntries[lyricsEntry] = val;
-                      val.Parent = tieStartNote.ParentVoiceEntry;
-                    }
-                  }
-                }
-                                delete this.openTieDict[tieNumber];
+                delete this.openTieDict[tieNumber];
               }
             }
           } catch (err) {
-                        const errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TieError", "Error while reading tie.");
-                        this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+            const errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TieError", "Error while reading tie.");
+            this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
           }
 
         }
       } else if (tieNodeList.length === 2) {
-                const tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
-                if (tieNumber >= 0) {
-                    const tie: Tie = this.openTieDict[tieNumber];
-                    const tieStartNote: Note = tie.Start;
-                    tieStartNote.Length.Add(this.currentNote.Length);
-                    tie.Fractions.push(this.currentNote.Length);
-                    if (this.currentNote.NoteBeam !== undefined) {
-                        const noteBeamIndex: number = this.currentNote.NoteBeam.Notes.indexOf(this.currentNote);
-                        if (noteBeamIndex === 0 && tie.BeamStartTimestamp === undefined) {
-              tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
-            }
-                        const noteBeam: Beam = this.currentNote.NoteBeam;
-                        noteBeam.Notes[noteBeamIndex] = tieStartNote;
-                        tie.TieBeam = noteBeam;
-          }
-                    for (let idx: number = 0, len: number = this.currentNote.NoteSlurs.length; idx < len; ++idx) {
-                        const slur: Slur = this.currentNote.NoteSlurs[idx];
-                        if (slur.StartNote === this.currentNote) {
-              slur.StartNote = tie.Start;
-              slur.StartNote.NoteSlurs.push(slur);
-            }
-                        if (slur.EndNote === this.currentNote) {
-              slur.EndNote = tie.Start;
-              slur.EndNote.NoteSlurs.push(slur);
-            }
-          }
-
-                    this.currentVoiceEntry.LyricsEntries.forEach((key: number, value: LyricsEntry): void => {
-            if (!tieStartNote.ParentVoiceEntry.LyricsEntries.containsKey(key)) {
-              tieStartNote.ParentVoiceEntry.LyricsEntries.setValue(key, value);
-              value.Parent = tieStartNote.ParentVoiceEntry;
-            }
-          });
-                    if (maxTieNoteFraction.lt(Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length))) {
+        const tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
+        if (tieNumber >= 0) {
+          const tie: Tie = this.openTieDict[tieNumber];
+          tie.AddNote(this.currentNote);
+          if (maxTieNoteFraction.lt(Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length))) {
             maxTieNoteFraction = Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length);
           }
-          // delete currentNote from Notes:
-                    const i: number = this.currentVoiceEntry.Notes.indexOf(this.currentNote);
-                    if (i !== -1) {
-            this.currentVoiceEntry.Notes.splice(i, 1);
-          }
         }
       }
     }
@@ -941,17 +835,17 @@ export class VoiceGenerator {
    * @returns {number}
    */
   private getNextAvailableNumberForTie(): number {
-        const keys: string[] = Object.keys(this.openTieDict);
-        if (keys.length === 0) {
+    const keys: string[] = Object.keys(this.openTieDict);
+    if (keys.length === 0) {
       return 1;
     }
-        keys.sort((a, b) => (+a - +b)); // FIXME Andrea: test
-        for (let i: number = 0; i < keys.length; i++) {
+    keys.sort((a, b) => (+a - +b)); // FIXME Andrea: test
+    for (let i: number = 0; i < keys.length; i++) {
       if ("" + (i + 1) !== keys[i]) {
         return i + 1;
       }
     }
-        return +(keys[keys.length - 1]) + 1;
+    return +(keys[keys.length - 1]) + 1;
   }
 
   /**
@@ -960,16 +854,16 @@ export class VoiceGenerator {
    * @returns {number}
    */
   private findCurrentNoteInTieDict(candidateNote: Note): number {
-        const openTieDict: { [_: number]: Tie; } = this.openTieDict;
-        for (const key in openTieDict) {
+    const openTieDict: { [_: number]: Tie; } = this.openTieDict;
+    for (const key in openTieDict) {
       if (openTieDict.hasOwnProperty(key)) {
-                const tie: Tie = openTieDict[key];
-                if (tie.Start.Pitch.FundamentalNote === candidateNote.Pitch.FundamentalNote && tie.Start.Pitch.Octave === candidateNote.Pitch.Octave) {
+        const tie: Tie = openTieDict[key];
+        if (tie.Pitch.FundamentalNote === candidateNote.Pitch.FundamentalNote && tie.Pitch.Octave === candidateNote.Pitch.Octave) {
           return +key;
         }
       }
     }
-        return -1;
+    return -1;
   }
 
   /**
@@ -979,15 +873,15 @@ export class VoiceGenerator {
    */
   private getTupletNoteDurationFromType(xmlNode: IXmlElement): Fraction {
     if (xmlNode.element("type") !== undefined) {
-            const typeNode: IXmlElement = xmlNode.element("type");
-            if (typeNode !== undefined) {
-                const type: string = typeNode.value;
-                try {
+      const typeNode: IXmlElement = xmlNode.element("type");
+      if (typeNode !== undefined) {
+        const type: string = typeNode.value;
+        try {
           return this.getNoteDurationFromType(type);
         } catch (e) {
-                    const errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError", "Invalid note duration.");
-                    this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
-                    throw new MusicSheetReadingException("", e);
+          const errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError", "Invalid note duration.");
+          this.musicSheet.SheetErrors.pushMeasureError(errorMsg);
+          throw new MusicSheetReadingException("", e);
         }
 
       }

+ 0 - 38
src/MusicalScore/VoiceData/Note.ts

@@ -107,29 +107,6 @@ export class Note {
         return this.Pitch === undefined;
     }
 
-    public calculateNoteLengthWithoutTie(): Fraction {
-        const withoutTieLength: Fraction = this.length.clone();
-        if (this.tie !== undefined) {
-            for (const fraction of this.tie.Fractions) {
-                withoutTieLength.Sub(fraction);
-            }
-        }
-        return withoutTieLength;
-    }
-    public calculateNoteOriginalLength(originalLength: Fraction = this.length): Fraction {
-        if (this.tie !== undefined) {
-            originalLength = this.calculateNoteLengthWithoutTie();
-        }
-        if (this.tuplet !== undefined) {
-            return this.length;
-        }
-        if (originalLength.Numerator > 1) {
-            const exp: number = Math.floor(Math.log(originalLength.Denominator) / Math.LN2) - this.calculateNumberOfNeededDots(originalLength);
-            originalLength.Denominator = Math.pow(2, exp);
-            originalLength.Numerator = 1;
-        }
-        return originalLength;
-    }
     public ToString(): string {
         if (this.pitch !== undefined) {
             return this.Pitch.ToString() + ", length: " + this.length.toString();
@@ -156,21 +133,6 @@ export class Note {
         }
         return false;
     }
-
-    /**
-     * Return the number of dots needed to represent the given [[Fraction]].
-     * @param fraction
-     * @returns {number}
-     */
-    private calculateNumberOfNeededDots(fraction: Fraction = this.length): number {
-        // FIXME (Andrea) Test if correct
-        if (this.tuplet === undefined) {
-            return Math.floor(Math.log(fraction.Numerator) / Math.LN2);
-        } else {
-            return 0;
-        }
-    }
-
 }
 
 export enum Appearance {

+ 15 - 11
src/MusicalScore/VoiceData/SourceStaffEntry.ts

@@ -197,11 +197,7 @@ export class SourceStaffEntry {
             const voiceEntry: VoiceEntry = this.VoiceEntries[idx];
             for (let idx2: number = 0, len2: number = voiceEntry.Notes.length; idx2 < len2; ++idx2) {
                 const note: Note = voiceEntry.Notes[idx2];
-                if (note.NoteTie !== undefined) {
-                    if (note.calculateNoteLengthWithoutTie().lt(duration)) {
-                        duration = note.calculateNoteLengthWithoutTie();
-                    }
-                } else if (note.Length.lt(duration)) {
+                if (note.Length.lt(duration)) {
                     duration = note.Length;
                 }
             }
@@ -216,14 +212,22 @@ export class SourceStaffEntry {
             for (let idx2: number = 0, len2: number = voiceEntry.Notes.length; idx2 < len2; ++idx2) {
                 const note: Note = voiceEntry.Notes[idx2];
                 if (note.NoteTie !== undefined) {
-                    if (duration < note.calculateNoteLengthWithoutTie()) {
-                        duration = note.calculateNoteLengthWithoutTie();
-                        for (let idx3: number = 0, len3: number = note.NoteTie.Fractions.length; idx3 < len3; ++idx3) {
-                            const fraction: Fraction = note.NoteTie.Fractions[idx3];
-                            duration.Add(fraction);
+                    // only add notes from this and after this sse!!
+                    const tieRestDuration: Fraction = Fraction.createFromFraction(note.Length);
+                    let addFollowingNotes: boolean = false;
+                    for (const n of note.NoteTie.Notes) {
+                        if (n === note) {
+                            addFollowingNotes = true;
+                            continue;
                         }
+                        if (addFollowingNotes) {
+                            tieRestDuration.Add(n.Length);
+                        }
+                    }
+                    if (duration.lt(note.NoteTie.Duration)) {
+                        duration = note.NoteTie.Duration;
                     }
-                } else if (duration < note.Length) {
+                } else if (duration.lt(note.Length)) {
                     duration = note.Length;
                 }
             }

+ 22 - 60
src/MusicalScore/VoiceData/Tie.ts

@@ -1,8 +1,7 @@
 import {Note} from "./Note";
-import {Beam} from "./Beam";
-import {Fraction} from "../../Common/DataObjects/Fraction";
-import {Tuplet} from "./Tuplet";
 import {BaseIdClass} from "../../Util/BaseIdClass";
+import { Fraction } from "../../Common/DataObjects/Fraction";
+import { Pitch } from "../../Common/DataObjects/Pitch";
 
 /**
  * A [[Tie]] connects two notes of the same pitch and name, indicating that they have to be played as a single note.
@@ -11,70 +10,33 @@ export class Tie extends BaseIdClass {
 
     constructor(note: Note) {
         super();
-        this.start = note;
+        this.AddNote(note);
     }
 
-    private start: Note;
-    private tieBeam: Beam;
-    private beamStartTimestamp: Fraction;
-    private tieTuplet: Tuplet;
-    private fractions: Fraction[] = [];
-    private noteHasBeenCreated: boolean[] = [];
-    private baseNoteYPosition: number;
+    private notes: Note[] = [];
 
-    public get Start(): Note {
-        return this.start;
+    public get Notes(): Note[] {
+        return this.notes;
     }
-    public set Start(value: Note) {
-        this.start = value;
-    }
-    public get TieBeam(): Beam {
-        return this.tieBeam;
-    }
-    public set TieBeam(value: Beam) {
-        this.tieBeam = value;
-    }
-    public get BeamStartTimestamp(): Fraction {
-        return this.beamStartTimestamp;
-    }
-    public set BeamStartTimestamp(value: Fraction) {
-        this.beamStartTimestamp = value;
-    }
-    public get TieTuplet(): Tuplet {
-        return this.tieTuplet;
-    }
-    public set TieTuplet(value: Tuplet) {
-        this.tieTuplet = value;
-    }
-    public get Fractions(): Fraction[] {
-        return this.fractions;
-    }
-    public set Fractions(value: Fraction[]) {
-        this.fractions = value;
-    }
-    public get NoteHasBeenCreated(): boolean[] {
-        return this.noteHasBeenCreated;
-    }
-    public set NoteHasBeenCreated(value: boolean[]) {
-        this.noteHasBeenCreated = value;
-    }
-    public get BaseNoteYPosition(): number {
-        return this.baseNoteYPosition;
-    }
-    public set BaseNoteYPosition(value: number) {
-        this.baseNoteYPosition = value;
-    }
-    public initializeBoolList(): void {
-        this.noteHasBeenCreated = new Array(this.fractions.length);
+
+    public get StartNote(): Note {
+        return this.notes[0];
     }
-    public allGraphicalNotesHaveBeenCreated(): boolean {
-        for (const b of this.noteHasBeenCreated) {
-            if (!b) {
-                return false;
-            }
+
+    public get Duration(): Fraction {
+        const duration: Fraction = new Fraction();
+        for (const note of this.notes) {
+            duration.Add(note.Length);
         }
+        return duration;
+    }
 
-        return true;
+    public get Pitch(): Pitch {
+        return this.StartNote.Pitch;
     }
 
+    public AddNote(note: Note): void {
+        this.notes.push(note);
+        note.NoteTie = this;
+    }
 }

+ 1 - 1
src/MusicalScore/VoiceData/VoiceEntry.ts

@@ -159,7 +159,7 @@ export class VoiceEntry {
             return;
         }
         const baseNote: Note = this.notes[0];
-        const baselength: Fraction = baseNote.calculateNoteLengthWithoutTie();
+        const baselength: Fraction = baseNote.Length;
         const baseVoice: Voice = voiceEntryWithOrnament.ParentVoice;
         const baseTimestamp: Fraction = voiceEntryWithOrnament.Timestamp;
         let currentTimestamp: Fraction = Fraction.createFromFraction(baseTimestamp);