Przeglądaj źródła

Fixed VoiceGenerator.ts

Andrea Condoluci 9 lat temu
rodzic
commit
5b21185182
2 zmienionych plików z 361 dodań i 352 usunięć
  1. 357 352
      src/MusicalScore/ScoreIO/VoiceGenerator.ts
  2. 4 0
      src/Util/collectionUtil.ts

+ 357 - 352
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -17,14 +17,23 @@ import {ArticulationEnum} from "../VoiceData/VoiceEntry";
 import {Slur} from "../VoiceData/Expressions/ContinuousExpressions/Slur";
 import {LyricsEntry} from "../VoiceData/Lyrics/LyricsEntry";
 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";
 
 type SlurReader = any;
 
 export class VoiceGenerator {
-    constructor(instrument: Instrument, voiceId: number, slurReader: SlurReader, mainVoice: Voice = null) {
+    constructor(instrument: Instrument, voiceId: number, slurReader: SlurReader, mainVoice: Voice = undefined) {
         this.musicSheet = instrument.GetMusicSheet;
         this.slurReader = slurReader;
-        if (mainVoice != null)
+        if (mainVoice !== undefined)
             this.voice = new LinkedVoice(instrument, voiceId, mainVoice);
         else {
             this.voice = new Voice(instrument, voiceId);
@@ -73,71 +82,70 @@ export class VoiceGenerator {
         this.currentMeasure = parentMeasure;
         try {
             this.currentNote = restNote ? this.addRestNote(noteDuration, divisions) : this.addSingleNote(noteNode, noteDuration, divisions, graceNote, chord, guitarPro);
-            if (this.lyricsReader != null && noteNode.Element("lyric") != null) {
-                this.lyricsReader.addLyricEntry(noteNode, this.currentVoiceEntry);
-                this.voice.Parent.HasLyrics = true;
-            }
-            var notationNode: IXmlElement = noteNode.Element("notations");
-            if (notationNode != null) {
-                var articNode: IXmlElement = null;
-                if (this.articulationReader != null) {
-                    this.readArticulations(notationNode, this.currentVoiceEntry);
-                }
-                var slurNodes: IXmlElement[] = null;
-                if (this.slurReader != null && (slurNodes = notationNode.Elements("slur")).Any())
-                    this.slurReader.addSlur(slurNodes, this.currentNote);
-                var tupletNodeList: IXmlElement[] = null;
+            // (*)
+            //if (this.lyricsReader !== undefined && noteNode.Element("lyric") !== undefined) {
+            //    this.lyricsReader.addLyricEntry(noteNode, this.currentVoiceEntry);
+            //    this.voice.Parent.HasLyrics = true;
+            //}
+            let notationNode: IXmlElement = noteNode.Element("notations");
+            if (notationNode !== undefined) {
+                let articNode: IXmlElement = undefined;
+                // (*)
+                //if (this.articulationReader !== undefined) {
+                //    this.readArticulations(notationNode, this.currentVoiceEntry);
+                //}
+                //let slurNodes: IXmlElement[] = undefined;
+                // (*)
+                //if (this.slurReader !== undefined && (slurNodes = notationNode.Elements("slur")))
+                //    this.slurReader.addSlur(slurNodes, this.currentNote);
+                let tupletNodeList: IXmlElement[] = undefined;
                 if ((tupletNodeList = notationNode.Elements("tuplet")))
                     this.openTupletNumber = this.addTuplet(noteNode, tupletNodeList);
-                if (notationNode.Element("arpeggiate") != null && !graceNote)
+                if (notationNode.Element("arpeggiate") !== undefined && !graceNote)
                     this.currentVoiceEntry.ArpeggiosNotesIndices.push(this.currentVoiceEntry.Notes.indexOf(this.currentNote));
-                var tiedNodeList: IXmlElement[] = null;
+                let tiedNodeList: IXmlElement[] = undefined;
                 if ((tiedNodeList = notationNode.Elements("tied")))
                     this.addTie(tiedNodeList, measureStartAbsoluteTimestamp, maxTieNoteFraction);
-                var toRemove: number[] = new number[]();
-                var openTieDictArr: KeyValuePair<number, Tie>[] = this.openTieDict.ToArray();
-                for (var idx: number = 0, len = openTieDictArr.length; idx < len; ++idx) {
-                    var openTie: KeyValuePair<number, Tie> = openTieDictArr[idx];
-                    var tie: Tie = openTie.Value;
-                    if (tie.Start.ParentStaffEntry.Timestamp + tie.Start.Length < this.currentStaffEntry.Timestamp)
-                        toRemove.push(openTie.Key);
-                }
-                for (var idx: number = 0, len = toRemove.length; idx < len; ++idx) {
-                    var i: number = toRemove[idx];
-                    this.openTieDict.Remove(i);
+
+                let openTieDict: { [_: number]: Tie; } = this.openTieDict;
+                for (let key in openTieDict) {
+                    let tie: Tie = openTieDict[key];
+                    if (Fraction.plus(tie.Start.ParentStaffEntry.Timestamp, tie.Start.Length).lt(this.currentStaffEntry.Timestamp))
+                        delete openTieDict[key];
                 }
             }
-            if (noteNode.Element("time-modification") != null && notationNode == null) {
+            if (noteNode.Element("time-modification") !== undefined && notationNode === undefined) {
                 this.handleTimeModificationNode(noteNode);
             }
         }
         catch (err) {
-            var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteError",
-                "Ignored erroneous Note.");
+            let errorMsg: string = ITextTranslation.translateText(
+                "ReaderErrorMessages/NoteError", "Ignored erroneous Note."
+            );
             this.musicSheet.SheetErrors.pushTemp(errorMsg);
         }
 
         return this.currentNote;
     }
     public checkForOpenGraceNotes(): void {
-        if (this.currentStaffEntry != null && this.currentStaffEntry.VoiceEntries.length == 0 && this.currentVoiceEntry.GraceVoiceEntriesBefore != null && this.currentVoiceEntry.GraceVoiceEntriesBefore.length > 0) {
-            var voice: Voice = this.currentVoiceEntry.ParentVoice;
-            var horizontalIndex: number = this.currentMeasure.VerticalSourceStaffEntryContainers.indexOf(this.currentStaffEntry.VerticalContainerParent);
-            var verticalIndex: number = this.currentStaffEntry.VerticalContainerParent.StaffEntries.indexOf(this.currentStaffEntry);
-            var previousStaffEntry: SourceStaffEntry = this.currentMeasure.getPreviousSourceStaffEntryFromIndex(verticalIndex, horizontalIndex);
-            if (previousStaffEntry != null) {
-                var previousVoiceEntry: VoiceEntry = null;
-                for (var idx: number = 0, len = previousStaffEntry.VoiceEntries.length; idx < len; ++idx) {
-                    var voiceEntry: VoiceEntry = previousStaffEntry.VoiceEntries[idx];
-                    if (voiceEntry.ParentVoice == voice) {
+        if (this.currentStaffEntry !== undefined && this.currentStaffEntry.VoiceEntries.length === 0 && this.currentVoiceEntry.GraceVoiceEntriesBefore !== undefined && this.currentVoiceEntry.GraceVoiceEntriesBefore.length > 0) {
+            let voice: Voice = this.currentVoiceEntry.ParentVoice;
+            let horizontalIndex: number = this.currentMeasure.VerticalSourceStaffEntryContainers.indexOf(this.currentStaffEntry.VerticalContainerParent);
+            let verticalIndex: number = this.currentStaffEntry.VerticalContainerParent.StaffEntries.indexOf(this.currentStaffEntry);
+            let previousStaffEntry: SourceStaffEntry = this.currentMeasure.getPreviousSourceStaffEntryFromIndex(verticalIndex, horizontalIndex);
+            if (previousStaffEntry !== undefined) {
+                let previousVoiceEntry: VoiceEntry = undefined;
+                for (let idx: number = 0, len = previousStaffEntry.VoiceEntries.length; idx < len; ++idx) {
+                    let voiceEntry: VoiceEntry = previousStaffEntry.VoiceEntries[idx];
+                    if (voiceEntry.ParentVoice === voice) {
                         previousVoiceEntry = voiceEntry;
-                        previousVoiceEntry.GraceVoiceEntriesAfter = VoiceEntry[];
-                        for (var idx2: number = 0, len2 = this.currentVoiceEntry.GraceVoiceEntriesBefore.length; idx2 < len2; ++idx2) {
-                            var graceVoiceEntry: VoiceEntry = this.currentVoiceEntry.GraceVoiceEntriesBefore[idx2];
+                        previousVoiceEntry.GraceVoiceEntriesAfter = [];
+                        for (let idx2: number = 0, len2 = this.currentVoiceEntry.GraceVoiceEntriesBefore.length; idx2 < len2; ++idx2) {
+                            let graceVoiceEntry: VoiceEntry = this.currentVoiceEntry.GraceVoiceEntriesBefore[idx2];
                             previousVoiceEntry.GraceVoiceEntriesAfter.push(graceVoiceEntry);
                         }
-                        this.currentVoiceEntry.GraceVoiceEntriesBefore.Clear();
-                        this.currentStaffEntry = null;
+                        this.currentVoiceEntry.GraceVoiceEntriesBefore = [];
+                        this.currentStaffEntry = undefined;
                         break;
                     }
                 }
@@ -146,13 +154,13 @@ export class VoiceGenerator {
     }
     public checkForStaffEntryLink(index: number, currentStaff: Staff, currentStaffEntry: SourceStaffEntry,
         currentMeasure: SourceMeasure): SourceStaffEntry {
-        var staffEntryLink: StaffEntryLink = new StaffEntryLink(this.currentVoiceEntry);
+        let staffEntryLink: StaffEntryLink = new StaffEntryLink(this.currentVoiceEntry);
         staffEntryLink.LinkStaffEntries.push(currentStaffEntry);
         currentStaffEntry.Link = staffEntryLink;
-        var linkMusicTimestamp: Fraction = new Fraction(this.currentVoiceEntry.Timestamp);
-        var verticalSourceStaffEntryContainer: VerticalSourceStaffEntryContainer = currentMeasure.getVerticalContainerByTimestamp(linkMusicTimestamp);
+        let linkMusicTimestamp: Fraction = this.currentVoiceEntry.Timestamp.clone();
+        let verticalSourceStaffEntryContainer: VerticalSourceStaffEntryContainer = currentMeasure.getVerticalContainerByTimestamp(linkMusicTimestamp);
         currentStaffEntry = verticalSourceStaffEntryContainer[index];
-        if (currentStaffEntry == null) {
+        if (currentStaffEntry === undefined) {
             currentStaffEntry = new SourceStaffEntry(verticalSourceStaffEntryContainer, currentStaff);
             verticalSourceStaffEntryContainer[index] = currentStaffEntry;
         }
@@ -162,25 +170,23 @@ export class VoiceGenerator {
         return currentStaffEntry;
     }
     public checkForOpenBeam(): void {
-        if (this.openBeam != null && this.currentNote != null)
+        if (this.openBeam !== undefined && this.currentNote !== undefined)
             this.handleOpenBeam();
     }
     public checkOpenTies(): void {
-        var toRemove: number[] = new number[]();
-        var openTieDictArr: KeyValuePair<number, Tie>[] = this.openTieDict.ToArray();
-        for (var idx: number = 0, len = openTieDictArr.length; idx < len; ++idx) {
-            var openTie: KeyValuePair<number, Tie> = openTieDictArr[idx];
-            var tie: Tie = openTie.Value;
-            if (tie.Start.ParentStaffEntry.Timestamp + tie.Start.Length < tie.Start.ParentStaffEntry.VerticalContainerParent.ParentMeasure.Duration)
-                toRemove.push(openTie.Key);
+        let toRemove: number[] = [];
+        let openTieDict: {[_: number]: Tie} = this.openTieDict;
+        for (let key in openTieDict) {
+            let tie: Tie = openTieDict[key];
+            if (Fraction.plus(tie.Start.ParentStaffEntry.Timestamp, tie.Start.Length).lt(tie.Start.ParentStaffEntry.VerticalContainerParent.ParentMeasure.Duration))
+                toRemove.push(key);
         }
-        for (var idx: number = 0, len = toRemove.length; idx < len; ++idx) {
-            var i: number = toRemove[idx];
-            this.openTieDict.Remove(i);
+        for (let key of toRemove) {
+            delete openTieDict[key];
         }
     }
     public hasVoiceEntry(): boolean {
-        return this.currentVoiceEntry != null;
+        return this.currentVoiceEntry !== undefined;
     }
     public getNoteDurationFromType(type: string): Fraction {
         switch (type) {
@@ -213,44 +219,45 @@ export class VoiceGenerator {
                 return new Fraction(4, 1);
             case "maxima":
                 return new Fraction(8, 1);
-            default:
-                {
-                    var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError",
-                        "Invalid note duration.");
-                    throw new MusicSheetReadingException(errorMsg, 0);
-                }
+            default: {
+                let errorMsg: string = ITextTranslation.translateText(
+                    "ReaderErrorMessages/NoteDurationError", "Invalid note duration."
+                );
+                throw new MusicSheetReadingException(errorMsg);
+            }
         }
     }
-    private readArticulations(notationNode: IXmlElement, currentVoiceEntry: VoiceEntry): void {
-        var articNode: IXmlElement;
-        if ((articNode = notationNode.Element("articulations")) != null)
-            this.articulationReader.addArticulationExpression(articNode, currentVoiceEntry);
-        var fermaNode: IXmlElement = null;
-        if ((fermaNode = notationNode.Element("fermata")) != null)
-            this.articulationReader.addFermata(fermaNode, currentVoiceEntry);
-        var tecNode: IXmlElement = null;
-        if ((tecNode = notationNode.Element("technical")) != null)
-            this.articulationReader.addTechnicalArticulations(tecNode, currentVoiceEntry);
-        var ornaNode: IXmlElement = null;
-        if ((ornaNode = notationNode.Element("ornaments")) != null)
-            this.articulationReader.addOrnament(ornaNode, currentVoiceEntry);
-    }
+    // (*)
+    //private readArticulations(notationNode: IXmlElement, currentVoiceEntry: VoiceEntry): void {
+    //    let articNode: IXmlElement;
+    //    if ((articNode = notationNode.Element("articulations")) !== undefined)
+    //        this.articulationReader.addArticulationExpression(articNode, currentVoiceEntry);
+    //    let fermaNode: IXmlElement = undefined;
+    //    if ((fermaNode = notationNode.Element("fermata")) !== undefined)
+    //        this.articulationReader.addFermata(fermaNode, currentVoiceEntry);
+    //    let tecNode: IXmlElement = undefined;
+    //    if ((tecNode = notationNode.Element("technical")) !== undefined)
+    //        this.articulationReader.addTechnicalArticulations(tecNode, currentVoiceEntry);
+    //    let ornaNode: IXmlElement = undefined;
+    //    if ((ornaNode = notationNode.Element("ornaments")) !== undefined)
+    //        this.articulationReader.addOrnament(ornaNode, currentVoiceEntry);
+    //}
     private addSingleNote(node: IXmlElement, noteDuration: number, divisions: number, graceNote: boolean, chord: boolean,
         guitarPro: boolean): Note {
-        var noteAlter: AccidentalEnum = AccidentalEnum.NONE;
-        var noteStep: NoteEnum = NoteEnum.C;
-        var noteOctave: number = 0;
-        var playbackInstrumentId: string = null;
-        var xmlnodeElementsArr: IXmlElement[] = node.Elements().ToArray();
-        for (var idx: number = 0, len = xmlnodeElementsArr.length; idx < len; ++idx) {
-            var noteElement: IXmlElement = xmlnodeElementsArr[idx];
+        let noteAlter: AccidentalEnum = AccidentalEnum.NONE;
+        let noteStep: NoteEnum = NoteEnum.C;
+        let noteOctave: number = 0;
+        let playbackInstrumentId: string = undefined;
+        let xmlnodeElementsArr: IXmlElement[] = node.Elements();
+        for (let idx: number = 0, len = xmlnodeElementsArr.length; idx < len; ++idx) {
+            let noteElement: IXmlElement = xmlnodeElementsArr[idx];
             try {
-                if (noteElement.Name == "pitch") {
-                    var noteElementsArr: IXmlElement[] = noteElement.Elements().ToArray();
-                    for (var idx2: number = 0, len2 = noteElementsArr.length; idx2 < len2; ++idx2) {
-                        var pitchElement: IXmlElement = noteElementsArr[idx2];
+                if (noteElement.Name === "pitch") {
+                    let noteElementsArr: IXmlElement[] = noteElement.Elements();
+                    for (let idx2: number = 0, len2 = noteElementsArr.length; idx2 < len2; ++idx2) {
+                        let pitchElement: IXmlElement = noteElementsArr[idx2];
                         try {
-                            if (pitchElement.Name == "step") {
+                            if (pitchElement.Name === "step") {
                                 try {
                                     switch (pitchElement.Value) {
                                         case "C":
@@ -291,328 +298,330 @@ export class VoiceGenerator {
                                     }
                                 }
                                 catch (e) {
-                                    var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NotePitchError",
-                                        "Invalid pitch while reading note.");
-                                    this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
-                                    throw new MusicSheetReadingException("", e, 0);
+                                    let errorMsg: string = ITextTranslation.translateText(
+                                        "ReaderErrorMessages/NotePitchError",
+                                        "Invalid pitch while reading note."
+                                    );
+                                    this.musicSheet.SheetErrors.pushTemp(errorMsg);
+                                    throw new MusicSheetReadingException("", e);
                                 }
 
                             }
-                            else if (pitchElement.Name == "alter") {
+                            else if (pitchElement.Name === "alter") {
                                 try {
-                                    noteAlter = <AccidentalEnum>StringToNumberConverter.ToInteger(pitchElement.Value);
+                                    noteAlter = parseInt(pitchElement.Value);
                                 }
                                 catch (e) {
-                                    var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteAlterationError",
+                                    let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteAlterationError",
                                         "Invalid alteration while reading note.");
-                                    this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
-                                    throw new MusicSheetReadingException("", e, 0);
+                                    this.musicSheet.SheetErrors.pushTemp(errorMsg);
+                                    throw new MusicSheetReadingException("", e);
                                 }
 
                             }
-                            else if (pitchElement.Name == "octave") {
+                            else if (pitchElement.Name === "octave") {
                                 try {
-                                    noteOctave = <number>StringToNumberConverter.ToInteger(pitchElement.Value);
+                                    noteOctave = parseInt(pitchElement.Value);
                                 }
                                 catch (e) {
-                                    var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteOctaveError",
+                                    let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteOctaveError",
                                         "Invalid octave value while reading note.");
-                                    this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
-                                    throw new MusicSheetReadingException("", e, 0);
+                                    this.musicSheet.SheetErrors.pushTemp(errorMsg);
+                                    throw new MusicSheetReadingException("", e);
                                 }
 
                             }
                         }
                         catch (ex) {
-                            Logger.DefaultLogger.LogError(LogLevel.NORMAL,
-                                "VoiceGenerator.addSingleNote read Step: ", ex);
+                            logging.log("VoiceGenerator.addSingleNote read Step: ", ex);
                         }
 
                     }
                 }
-                else if (noteElement.Name == "unpitched") {
-                    var displayStep: IXmlElement = null;
-                    if ((displayStep = noteElement.Element("display-step")) != null) {
-                        noteStep = <NoteEnum>Enum.Parse(/*typeof*/NoteEnum, displayStep.Value);
+                else if (noteElement.Name === "unpitched") {
+                    let displayStep: IXmlElement = undefined;
+                    if ((displayStep = noteElement.Element("display-step")) !== undefined) {
+                        noteStep = NoteEnum[displayStep.Value.toUpperCase()];
                     }
-                    var octave: IXmlElement = null;
-                    if ((octave = noteElement.Element("display-octave")) != null) {
-                        noteOctave = <number>(StringToNumberConverter.ToInteger(octave.Value));
+                    let octave: IXmlElement = undefined;
+                    if ((octave = noteElement.Element("display-octave")) !== undefined) {
+                        noteOctave = parseInt(octave.Value);
                         if (guitarPro)
                             noteOctave += 1;
                     }
                 }
-                else if (noteElement.Name == "instrument") {
-                    if (noteElement.FirstAttribute != null)
+                else if (noteElement.Name === "instrument") {
+                    if (noteElement.FirstAttribute !== undefined)
                         playbackInstrumentId = noteElement.FirstAttribute.Value;
                 }
             }
             catch (ex) {
-                Logger.DefaultLogger.LogError(LogLevel.NORMAL, "VoiceGenerator.addSingleNote: ", ex);
+                logging.log("VoiceGenerator.addSingleNote: ", ex);
             }
 
         }
-        noteOctave -= Pitch.XmlOctaveDifference;
-        var pitch: Pitch = new Pitch(noteStep, noteOctave, noteAlter);
-        var noteLength: Fraction = new Fraction(noteDuration, divisions);
-        var note: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, noteLength, pitch);
+        noteOctave -= Pitch.OctaveXmlDifference;
+        let pitch: Pitch = new Pitch(noteStep, noteOctave, noteAlter);
+        let noteLength: Fraction = new Fraction(noteDuration, divisions);
+        let note: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, noteLength, pitch);
         note.PlaybackInstrumentId = playbackInstrumentId;
         if (!graceNote)
             this.currentVoiceEntry.Notes.push(note);
         else this.handleGraceNote(node, note);
-        if (node.Elements("beam").Any() && !chord) {
+        if (node.Elements("beam") && !chord) {
             this.createBeam(node, note, graceNote);
         }
         return note;
     }
     private addRestNote(noteDuration: number, divisions: number): Note {
-        var restFraction: Fraction = new Fraction(noteDuration, divisions);
-        var restNote: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, restFraction, null);
+        let restFraction: Fraction = new Fraction(noteDuration, divisions);
+        let restNote: Note = new Note(this.currentVoiceEntry, this.currentStaffEntry, restFraction, undefined);
         this.currentVoiceEntry.Notes.push(restNote);
-        if (this.openBeam != null)
+        if (this.openBeam !== undefined)
             this.openBeam.ExtendedNoteList.push(restNote);
         return restNote;
     }
     private createBeam(node: IXmlElement, note: Note, grace: boolean): void {
         try {
-            var beamNode: IXmlElement = node.Element("beam");
-            var beamAttr: IXmlAttribute = null;
-            if (beamNode != null && beamNode.HasAttributes)
+            let beamNode: IXmlElement = node.Element("beam");
+            let beamAttr: IXmlAttribute = undefined;
+            if (beamNode !== undefined && beamNode.HasAttributes)
                 beamAttr = beamNode.Attribute("number");
-            if (beamAttr != null) {
-                var beamNumber: number = StringToNumberConverter.ToInteger(beamAttr.Value);
-                var mainBeamNode: IXmlElement[] = node.Elements("beam");
-                var currentBeamTag: string = mainBeamNode.First().Value;
-                if (beamNumber == 1 && mainBeamNode != null) {
-                    if (currentBeamTag == "begin" && this.lastBeamTag != currentBeamTag) {
+            if (beamAttr !== undefined) {
+                let beamNumber: number = parseInt(beamAttr.Value);
+                let mainBeamNode: IXmlElement[] = node.Elements("beam");
+                let currentBeamTag: string = mainBeamNode[0].Value;
+                if (beamNumber === 1 && mainBeamNode !== undefined) {
+                    if (currentBeamTag === "begin" && this.lastBeamTag !== currentBeamTag) {
                         if (grace) {
-                            if (this.openGraceBeam != null)
+                            if (this.openGraceBeam !== undefined)
                                 this.handleOpenBeam();
                             this.openGraceBeam = new Beam();
                         }
                         else {
-                            if (this.openBeam != null)
+                            if (this.openBeam !== undefined)
                                 this.handleOpenBeam();
                             this.openBeam = new Beam();
                         }
                     }
                     this.lastBeamTag = currentBeamTag;
                 }
-                var sameVoiceEntry: boolean = false;
+                let sameVoiceEntry: boolean = false;
                 if (grace) {
-                    if (this.openGraceBeam == null)
-                        return
-                    for (var idx: number = 0, len = this.openGraceBeam.Notes.length; idx < len; ++idx) {
-                        var beamNote: Note = this.openGraceBeam.Notes[idx];
-                        if (this.currentVoiceEntry == beamNote.ParentVoiceEntry)
+                    if (this.openGraceBeam === undefined)
+                        return;
+                    for (let idx: number = 0, len = this.openGraceBeam.Notes.length; idx < len; ++idx) {
+                        let beamNote: Note = this.openGraceBeam.Notes[idx];
+                        if (this.currentVoiceEntry === beamNote.ParentVoiceEntry)
                             sameVoiceEntry = true;
                     }
                     if (!sameVoiceEntry) {
                         this.openGraceBeam.addNoteToBeam(note);
-                        if (currentBeamTag == "end" && beamNumber == 1)
-                            this.openGraceBeam = null;
+                        if (currentBeamTag === "end" && beamNumber === 1)
+                            this.openGraceBeam = undefined;
                     }
                 }
                 else {
-                    if (this.openBeam == null)
-                        return
-                    for (var idx: number = 0, len = this.openBeam.Notes.length; idx < len; ++idx) {
-                        var beamNote: Note = this.openBeam.Notes[idx];
-                        if (this.currentVoiceEntry == beamNote.ParentVoiceEntry)
+                    if (this.openBeam === undefined)
+                        return;
+                    for (let idx: number = 0, len = this.openBeam.Notes.length; idx < len; ++idx) {
+                        let beamNote: Note = this.openBeam.Notes[idx];
+                        if (this.currentVoiceEntry === beamNote.ParentVoiceEntry)
                             sameVoiceEntry = true;
                     }
                     if (!sameVoiceEntry) {
                         this.openBeam.addNoteToBeam(note);
-                        if (currentBeamTag == "end" && beamNumber == 1)
-                            this.openBeam = null;
+                        if (currentBeamTag === "end" && beamNumber === 1)
+                            this.openBeam = undefined;
                     }
                 }
             }
         }
         catch (e) {
-            var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/BeamError",
+            let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/BeamError",
                 "Error while reading beam.");
-            this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
-            throw new MusicSheetReadingException("", e, 0);
+            this.musicSheet.SheetErrors.pushTemp(errorMsg);
+            throw new MusicSheetReadingException("", e);
         }
 
     }
     private handleOpenBeam(): void {
-        if (this.openBeam.Notes.length == 1) {
-            var beamNote: Note = this.openBeam.Notes[0];
-            beamNote.NoteBeam = null;
-            this.openBeam = null;
+        if (this.openBeam.Notes.length === 1) {
+            let beamNote: Note = this.openBeam.Notes[0];
+            beamNote.NoteBeam = undefined;
+            this.openBeam = undefined;
             return
         }
-        if (this.currentNote == this.openBeam.Notes.Last())
-            this.openBeam = null;
+        if (this.currentNote === CollectionUtil.last(this.openBeam.Notes))
+            this.openBeam = undefined;
         else {
-            var beamLastNote: Note = this.openBeam.Notes.Last();
-            var beamLastNoteStaffEntry: SourceStaffEntry = beamLastNote.ParentStaffEntry;
-            var horizontalIndex: number = this.currentMeasure.getVerticalContainerIndexByTimestamp(beamLastNoteStaffEntry.Timestamp);
-            var verticalIndex: number = beamLastNoteStaffEntry.VerticalContainerParent.StaffEntries.indexOf(beamLastNoteStaffEntry);
+            let beamLastNote: Note = CollectionUtil.last(this.openBeam.Notes);
+            let beamLastNoteStaffEntry: SourceStaffEntry = beamLastNote.ParentStaffEntry;
+            let horizontalIndex: number = this.currentMeasure.getVerticalContainerIndexByTimestamp(beamLastNoteStaffEntry.Timestamp);
+            let verticalIndex: number = beamLastNoteStaffEntry.VerticalContainerParent.StaffEntries.indexOf(beamLastNoteStaffEntry);
             if (horizontalIndex < this.currentMeasure.VerticalSourceStaffEntryContainers.length - 1) {
-                var nextStaffEntry: SourceStaffEntry = this.currentMeasure.VerticalSourceStaffEntryContainers[horizontalIndex + 1][verticalIndex];
-                if (nextStaffEntry != null) {
-                    for (var idx: number = 0, len = nextStaffEntry.VoiceEntries.length; idx < len; ++idx) {
-                        var voiceEntry: VoiceEntry = nextStaffEntry.VoiceEntries[idx];
-                        if (voiceEntry.ParentVoice == this.voice) {
-                            var candidateNote: Note = voiceEntry.Notes[0];
+                let nextStaffEntry: SourceStaffEntry = this.currentMeasure.VerticalSourceStaffEntryContainers[horizontalIndex + 1][verticalIndex];
+                if (nextStaffEntry !== undefined) {
+                    for (let idx: number = 0, len = nextStaffEntry.VoiceEntries.length; idx < len; ++idx) {
+                        let voiceEntry: VoiceEntry = nextStaffEntry.VoiceEntries[idx];
+                        if (voiceEntry.ParentVoice === this.voice) {
+                            let candidateNote: Note = voiceEntry.Notes[0];
                             if (candidateNote.Length <= new Fraction(1, 8)) {
                                 this.openBeam.addNoteToBeam(candidateNote);
-                                this.openBeam = null;
+                                this.openBeam = undefined;
                             }
                             else {
-                                this.openBeam = null;
+                                this.openBeam = undefined;
                             }
                         }
                     }
                 }
             }
             else {
-                this.openBeam = null;
+                this.openBeam = undefined;
             }
         }
     }
     private handleGraceNote(node: IXmlElement, note: Note): void {
-        var graceChord: boolean = false;
-        var type: string = "";
-        if (node.Elements("type").Any()) {
-            var typeNode: IXmlElement[] = node.Elements("type");
-            if (typeNode.Any()) {
-                type = typeNode.First().Value;
+        let graceChord: boolean = false;
+        let type: string = "";
+        if (node.Elements("type")) {
+            let typeNode: IXmlElement[] = node.Elements("type");
+            if (typeNode) {
+                type = typeNode[0].Value;
                 try {
                     note.Length = this.getNoteDurationFromType(type);
                     note.Length.Numerator = 1;
                 }
                 catch (e) {
-                    var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError",
+                    let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError",
                         "Invalid note duration.");
-                    this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
-                    throw new MusicSheetReadingException("", e, 0);
+                    this.musicSheet.SheetErrors.pushTemp(errorMsg);
+                    throw new MusicSheetReadingException("", e);
                 }
 
             }
         }
-        var graceNode: IXmlElement = node.Element("grace");
-        if (graceNode != null && graceNode.Attributes().Any()) {
-            if (graceNode.Attribute("slash") != null) {
-                var slash: string = graceNode.Attribute("slash").Value;
-                if (slash == "yes")
+        let graceNode: IXmlElement = node.Element("grace");
+        if (graceNode !== undefined && graceNode.Attributes()) {
+            if (graceNode.Attribute("slash") !== undefined) {
+                let slash: string = graceNode.Attribute("slash").Value;
+                if (slash === "yes")
                     note.GraceNoteSlash = true;
             }
         }
-        if (node.Element("chord") != null)
+        if (node.Element("chord") !== undefined)
             graceChord = true;
-        var graceVoiceEntry: VoiceEntry = null;
+        let graceVoiceEntry: VoiceEntry = undefined;
         if (!graceChord) {
-            graceVoiceEntry = new VoiceEntry(new Fraction(new Fraction(0, 1)), this.currentVoiceEntry.ParentVoice,
-                this.currentStaffEntry);
-            if (this.currentVoiceEntry.GraceVoiceEntriesBefore == null)
-                this.currentVoiceEntry.GraceVoiceEntriesBefore = new List<VoiceEntry>();
+            graceVoiceEntry = new VoiceEntry(
+                new Fraction(0, 1), this.currentVoiceEntry.ParentVoice, this.currentStaffEntry
+            );
+            if (this.currentVoiceEntry.GraceVoiceEntriesBefore === undefined)
+                this.currentVoiceEntry.GraceVoiceEntriesBefore = [];
             this.currentVoiceEntry.GraceVoiceEntriesBefore.push(graceVoiceEntry);
         }
         else {
-            if (this.currentVoiceEntry.GraceVoiceEntriesBefore != null && this.currentVoiceEntry.GraceVoiceEntriesBefore.length > 0)
-                graceVoiceEntry = this.currentVoiceEntry.GraceVoiceEntriesBefore.Last();
+            if (this.currentVoiceEntry.GraceVoiceEntriesBefore !== undefined && this.currentVoiceEntry.GraceVoiceEntriesBefore.length > 0)
+                graceVoiceEntry = CollectionUtil.last(this.currentVoiceEntry.GraceVoiceEntriesBefore);
         }
-        if (graceVoiceEntry != null) {
+        if (graceVoiceEntry !== undefined) {
             graceVoiceEntry.Notes.push(note);
             note.ParentVoiceEntry = graceVoiceEntry;
         }
     }
     private addTuplet(node: IXmlElement, tupletNodeList: IXmlElement[]): number {
-        if (tupletNodeList != null && tupletNodeList.length() > 1) {
-            var timeModNode: IXmlElement = node.Element("time-modification");
-            if (timeModNode != null)
+        if (tupletNodeList !== undefined && tupletNodeList.length > 1) {
+            let timeModNode: IXmlElement = node.Element("time-modification");
+            if (timeModNode !== undefined)
                 timeModNode = timeModNode.Element("actual-notes");
-            var tupletNodeListArr: IXmlElement[] = tupletNodeList.ToArray();
-            for (var idx: number = 0, len = tupletNodeListArr.length; idx < len; ++idx) {
-                var tupletNode: IXmlElement = tupletNodeListArr[idx];
-                if (tupletNode != null && tupletNode.Attributes().Any()) {
-                    var type: string = tupletNode.Attribute("type").Value;
-                    if (type == "start") {
-                        var tupletNumber: number = 1;
-                        if (tupletNode.Attribute("nummber") != null)
-                            tupletNumber = StringToNumberConverter.ToInteger(tupletNode.Attribute("number").Value);
-                        var tupletLabelNumber: number = 0;
-                        if (timeModNode != null) {
+            let tupletNodeListArr: IXmlElement[] = tupletNodeList;
+            for (let idx: number = 0, len = tupletNodeListArr.length; idx < len; ++idx) {
+                let tupletNode: IXmlElement = tupletNodeListArr[idx];
+                if (tupletNode !== undefined && tupletNode.Attributes()) {
+                    let type: string = tupletNode.Attribute("type").Value;
+                    if (type === "start") {
+                        let tupletNumber: number = 1;
+                        if (tupletNode.Attribute("nummber") !== undefined)
+                            tupletNumber = parseInt(tupletNode.Attribute("number").Value);
+                        let tupletLabelNumber: number = 0;
+                        if (timeModNode !== undefined) {
                             try {
-                                tupletLabelNumber = StringToNumberConverter.ToInteger(timeModNode.Value);
+                                tupletLabelNumber = parseInt(timeModNode.Value);
                             }
                             catch (e) {
-                                var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TupletNoteDurationError",
+                                let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TupletNoteDurationError",
                                     "Invalid tuplet note duration.");
-                                this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
-                                throw new MusicSheetReadingException("", e, 0);
+                                this.musicSheet.SheetErrors.pushTemp(errorMsg);
+                                throw new MusicSheetReadingException("", e);
                             }
 
                         }
-                        var tuplet: Tuplet = new Tuplet(tupletLabelNumber);
-                        if (this.tupletDict.ContainsKey(tupletNumber)) {
-                            this.tupletDict.Remove(tupletNumber);
-                            if (this.tupletDict.length == 0)
+                        let tuplet: Tuplet = new Tuplet(tupletLabelNumber);
+                        if (this.tupletDict[tupletNumber] !== undefined) {
+                            delete this.tupletDict[tupletNumber];
+                            if (Object.keys(this.tupletDict).length === 0)
                                 this.openTupletNumber = 0;
-                            else if (this.tupletDict.length > 1)
+                            else if (Object.keys(this.tupletDict).length > 1)
                                 this.openTupletNumber--;
                         }
-                        this.tupletDict.push(tupletNumber, tuplet);
-                        var subnotelist: List<Note> = new List<Note>();
+                        this.tupletDict[tupletNumber] = tuplet;
+                        let subnotelist: Note[] = [];
                         subnotelist.push(this.currentNote);
                         tuplet.Notes.push(subnotelist);
                         tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
                         this.currentNote.NoteTuplet = tuplet;
                         this.openTupletNumber = tupletNumber;
                     }
-                    else if (type == "stop") {
-                        var tupletNumber: number = 1;
-                        if (tupletNode.Attribute("nummber") != null)
-                            tupletNumber = StringToNumberConverter.ToInteger(tupletNode.Attribute("number").Value);
-                        if (this.tupletDict.ContainsKey(tupletNumber)) {
-                            var tuplet: Tuplet = this.tupletDict[tupletNumber];
-                            var subnotelist: List<Note> = new List<Note>();
+                    else if (type === "stop") {
+                        let tupletNumber: number = 1;
+                        if (tupletNode.Attribute("number") !== undefined)
+                            tupletNumber = parseInt(tupletNode.Attribute("number").Value);
+                        let tuplet: Tuplet = this.tupletDict[tupletNumber];
+                        if (tuplet !== undefined) {
+                            let subnotelist: Note[] = [];
                             subnotelist.push(this.currentNote);
                             tuplet.Notes.push(subnotelist);
                             tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
                             this.currentNote.NoteTuplet = tuplet;
-                            this.tupletDict.Remove(tupletNumber);
-                            if (this.tupletDict.length == 0)
+                            delete this.tupletDict[tupletNumber];
+                            if (Object.keys(this.tupletDict).length === 0)
                                 this.openTupletNumber = 0;
-                            else if (this.tupletDict.length > 1)
+                            else if (Object.keys(this.tupletDict).length > 1)
                                 this.openTupletNumber--;
                         }
                     }
                 }
             }
         }
-        else if (tupletNodeList.First() != null) {
-            var n: IXmlElement = tupletNodeList.First();
+        else if (tupletNodeList[0] !== undefined) {
+            let n: IXmlElement = tupletNodeList[0];
             if (n.HasAttributes) {
-                var type: string = n.Attribute("type").Value;
-                var tupletnumber: number = 1;
-                var noTupletNumbering: boolean = false;
+                let type: string = n.Attribute("type").Value;
+                let tupletnumber: number = 1;
+                let noTupletNumbering: boolean = false;
                 try {
-                    if (n.Attribute("number") != null)
-                        tupletnumber = StringToNumberConverter.ToInteger(n.Attribute("number").Value);
+                    if (n.Attribute("number") !== undefined)
+                        tupletnumber = parseInt(n.Attribute("number").Value);
                 }
                 catch (err) {
                     noTupletNumbering = true;
                 }
 
-                if (type == "start") {
-                    var tupletLabelNumber: number = 0;
-                    var timeModNode: IXmlElement = node.Element("time-modification");
-                    if (timeModNode != null)
+                if (type === "start") {
+                    let tupletLabelNumber: number = 0;
+                    let timeModNode: IXmlElement = node.Element("time-modification");
+                    if (timeModNode !== undefined)
                         timeModNode = timeModNode.Element("actual-notes");
-                    if (timeModNode != null) {
+                    if (timeModNode !== undefined) {
                         try {
-                            tupletLabelNumber = StringToNumberConverter.ToInteger(timeModNode.Value);
+                            tupletLabelNumber = parseInt(timeModNode.Value);
                         }
                         catch (e) {
-                            var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TupletNoteDurationError",
+                            let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TupletNoteDurationError",
                                 "Invalid tuplet note duration.");
-                            this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
-                            throw new MusicSheetReadingException("", e, 0);
+                            this.musicSheet.SheetErrors.pushTemp(errorMsg);
+                            throw new MusicSheetReadingException("", e);
                         }
 
                     }
@@ -620,36 +629,32 @@ export class VoiceGenerator {
                         this.openTupletNumber++;
                         tupletnumber = this.openTupletNumber;
                     }
-                    var tuplet: Tuplet;
-                    if (this.tupletDict.ContainsKey(tupletnumber)) {
-                        tuplet = this.tupletDict[tupletnumber];
-                    }
-                    else {
-                        tuplet = new Tuplet(tupletLabelNumber);
-                        this.tupletDict.push(tupletnumber, tuplet);
+                    let tuplet: Tuplet = this.tupletDict[tupletnumber];
+                    if (tuplet === undefined) {
+                        tuplet = this.tupletDict[tupletnumber] = new Tuplet(tupletLabelNumber);
                     }
-                    var subnotelist: List<Note> = new List<Note>();
+                    let subnotelist: Note[] = [];
                     subnotelist.push(this.currentNote);
                     tuplet.Notes.push(subnotelist);
                     tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
                     this.currentNote.NoteTuplet = tuplet;
                     this.openTupletNumber = tupletnumber;
                 }
-                else if (type == "stop") {
+                else if (type === "stop") {
                     if (noTupletNumbering)
                         tupletnumber = this.openTupletNumber;
-                    if (this.tupletDict.ContainsKey(tupletnumber)) {
-                        var tuplet: Tuplet = this.tupletDict[this.openTupletNumber];
-                        var subnotelist: List<Note> = new List<Note>();
+                    let tuplet: Tuplet = this.tupletDict[this.openTupletNumber];
+                    if (tuplet !== undefined) {
+                        let subnotelist: Note[] = [];
                         subnotelist.push(this.currentNote);
                         tuplet.Notes.push(subnotelist);
                         tuplet.Fractions.push(this.getTupletNoteDurationFromType(node));
                         this.currentNote.NoteTuplet = tuplet;
-                        if (this.tupletDict.length == 0)
+                        if (Object.keys(this.tupletDict).length === 0)
                             this.openTupletNumber = 0;
-                        else if (this.tupletDict.length > 1)
+                        else if (Object.keys(this.tupletDict).length > 1)
                             this.openTupletNumber--;
-                        this.tupletDict.Remove(tupletnumber);
+                        delete this.tupletDict[tupletnumber];
                     }
                 }
             }
@@ -657,16 +662,16 @@ export class VoiceGenerator {
         return this.openTupletNumber;
     }
     private handleTimeModificationNode(noteNode: IXmlElement): void {
-        if (this.tupletDict.length != 0) {
+        if (Object.keys(this.tupletDict).length !== 0) {
             try {
-                var tuplet: Tuplet = this.tupletDict[this.openTupletNumber];
-                var notes: List<Note> = tuplet.Notes.Last();
-                var lastTupletVoiceEntry: VoiceEntry = notes[0].ParentVoiceEntry;
-                var noteList: List<Note>;
-                if (lastTupletVoiceEntry.Timestamp == this.currentVoiceEntry.Timestamp)
+                let tuplet: Tuplet = this.tupletDict[this.openTupletNumber];
+                let notes: Note[] = CollectionUtil.last(tuplet.Notes);
+                let lastTupletVoiceEntry: VoiceEntry = notes[0].ParentVoiceEntry;
+                let noteList: Note[];
+                if (lastTupletVoiceEntry.Timestamp === this.currentVoiceEntry.Timestamp)
                     noteList = notes;
                 else {
-                    noteList = new List<Note>();
+                    noteList = [];
                     tuplet.Notes.push(noteList);
                     tuplet.Fractions.push(this.getTupletNoteDurationFromType(noteNode));
                 }
@@ -674,93 +679,93 @@ export class VoiceGenerator {
                 this.currentNote.NoteTuplet = tuplet;
             }
             catch (ex) {
-                var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TupletNumberError",
+                let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TupletNumberError",
                     "Invalid tuplet number.");
-                this.musicSheet.SheetErrors.AddErrorMessageInTempList(errorMsg);
+                this.musicSheet.SheetErrors.pushTemp(errorMsg);
                 throw ex;
             }
 
         }
         else if (this.currentVoiceEntry.Notes.length > 0) {
-            var firstNote: Note = this.currentVoiceEntry.Notes[0];
-            if (firstNote.NoteTuplet != null) {
-                var tuplet: Tuplet = firstNote.NoteTuplet;
-                var notes: List<Note> = tuplet.Notes.Last();
+            let firstNote: Note = this.currentVoiceEntry.Notes[0];
+            if (firstNote.NoteTuplet !== undefined) {
+                let tuplet: Tuplet = firstNote.NoteTuplet;
+                let notes: Note[] = CollectionUtil.last(tuplet.Notes);
                 notes.push(this.currentNote);
                 this.currentNote.NoteTuplet = tuplet;
             }
         }
     }
     private addTie(tieNodeList: IXmlElement[], measureStartAbsoluteTimestamp: Fraction, maxTieNoteFraction: Fraction): void {
-        if (tieNodeList != null) {
-            if (tieNodeList.length() == 1) {
-                var tieNode: IXmlElement = tieNodeList.First();
-                if (tieNode != null && tieNode.Attributes().Any()) {
-                    var type: string = tieNode.Attribute("type").Value;
+        if (tieNodeList !== undefined) {
+            if (tieNodeList.length === 1) {
+                let tieNode: IXmlElement = tieNodeList[0];
+                if (tieNode !== undefined && tieNode.Attributes()) {
+                    let type: string = tieNode.Attribute("type").Value;
                     try {
-                        if (type == "start") {
-                            var number: number = this.findCurrentNoteInTieDict(this.currentNote);
+                        if (type === "start") {
+                            let number: number = this.findCurrentNoteInTieDict(this.currentNote);
                             if (number < 0)
-                                this.openTieDict.Remove(number);
-                            var newTieNumber: number = this.getNextAvailableNumberForTie();
-                            var tie: Tie = new Tie(this.currentNote);
-                            this.openTieDict.push(newTieNumber, tie);
-                            if (this.currentNote.NoteBeam != null)
-                                if (this.currentNote.NoteBeam.Notes[0] == this.currentNote) {
+                                delete this.openTieDict[number];
+                            let newTieNumber: number = this.getNextAvailableNumberForTie();
+                            let 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 = measureStartAbsoluteTimestamp + this.currentVoiceEntry.Timestamp;
                                 }
                                 else {
-                                    for (var idx: number = 0, len = this.currentNote.NoteBeam.Notes.length; idx < len; ++idx) {
-                                        var note: Note = this.currentNote.NoteBeam.Notes[idx];
-                                        if (note.NoteTie != null && note.NoteTie != tie && note.NoteTie.BeamStartTimestamp != null) {
+                                    for (let idx: number = 0, len = this.currentNote.NoteBeam.Notes.length; idx < len; ++idx) {
+                                        let 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 == this.currentNote.NoteBeam.Notes.Last())
+                                    if (this.currentNote === CollectionUtil.last(this.currentNote.NoteBeam.Notes))
                                         tie.BeamStartTimestamp = measureStartAbsoluteTimestamp + this.currentVoiceEntry.Timestamp;
                                 }
                         }
-                        else if (type == "stop") {
-                            var tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
-                            var tie: Tie = this.openTieDict[tieNumber];
+                        else if (type === "stop") {
+                            let tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
+                            let tie: Tie = this.openTieDict[tieNumber];
                             if (tie !== undefined) {
-                                var tieStartNote: Note = tie.Start;
+                                let tieStartNote: Note = tie.Start;
                                 tieStartNote.NoteTie = tie;
                                 tieStartNote.Length.Add(this.currentNote.Length);
                                 tie.Fractions.push(this.currentNote.Length);
                                 if (maxTieNoteFraction < this.currentStaffEntry.Timestamp + this.currentNote.Length)
                                     maxTieNoteFraction = this.currentStaffEntry.Timestamp + this.currentNote.Length;
-                                this.currentVoiceEntry.Notes.Remove(this.currentNote);
-                                if (this.currentVoiceEntry.Articulations.length == 1 && this.currentVoiceEntry.Articulations[0] == ArticulationEnum.fermata && !tieStartNote.ParentVoiceEntry.Articulations.Contains(ArticulationEnum.fermata))
+                                delete this.currentVoiceEntry.Notes[this.currentNote];
+                                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 != null) {
-                                    var noteBeamIndex: number = this.currentNote.NoteBeam.Notes.indexOf(this.currentNote);
-                                    if (noteBeamIndex == 0 && tie.BeamStartTimestamp == null)
+                                if (this.currentNote.NoteBeam !== undefined) {
+                                    let noteBeamIndex: number = this.currentNote.NoteBeam.Notes.indexOf(this.currentNote);
+                                    if (noteBeamIndex === 0 && tie.BeamStartTimestamp === undefined)
                                         tie.BeamStartTimestamp = measureStartAbsoluteTimestamp + this.currentVoiceEntry.Timestamp;
-                                    var noteBeam: Beam = this.currentNote.NoteBeam;
+                                    let noteBeam: Beam = this.currentNote.NoteBeam;
                                     noteBeam.Notes[noteBeamIndex] = tieStartNote;
                                     tie.TieBeam = noteBeam;
                                 }
-                                if (this.currentNote.NoteTuplet != null) {
-                                    var noteTupletIndex: number = this.currentNote.NoteTuplet.getNoteIndex(this.currentNote);
-                                    var index: number = this.currentNote.NoteTuplet.Notes[noteTupletIndex].indexOf(this.currentNote);
-                                    var noteTuplet: Tuplet = this.currentNote.NoteTuplet;
+                                if (this.currentNote.NoteTuplet !== undefined) {
+                                    let noteTupletIndex: number = this.currentNote.NoteTuplet.getNoteIndex(this.currentNote);
+                                    let index: number = this.currentNote.NoteTuplet.Notes[noteTupletIndex].indexOf(this.currentNote);
+                                    let noteTuplet: Tuplet = this.currentNote.NoteTuplet;
                                     noteTuplet.Notes[noteTupletIndex][index] = tieStartNote;
                                     tie.TieTuplet = noteTuplet;
                                 }
-                                for (var idx: number = 0, len = this.currentNote.NoteSlurs.length; idx < len; ++idx) {
-                                    var slur: Slur = this.currentNote.NoteSlurs[idx];
-                                    if (slur.StartNote == this.currentNote) {
+                                for (let idx: number = 0, len = this.currentNote.NoteSlurs.length; idx < len; ++idx) {
+                                    let 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) {
+                                    if (slur.EndNote === this.currentNote) {
                                         slur.EndNote = tie.Start;
                                         slur.EndNote.NoteSlurs.push(slur);
                                     }
                                 }
-                                //var lyricsEntriesArr: KeyValuePair<number, LyricsEntry>[] = this.currentVoiceEntry.LyricsEntries.ToArray();
+                                //let lyricsEntriesArr: KeyValuePair<number, LyricsEntry>[] = this.currentVoiceEntry.LyricsEntries.ToArray();
                                 for (let lyricsEntry in this.currentVoiceEntry.LyricsEntries) {
                                     let val: LyricsEntry = this.currentVoiceEntry.LyricsEntries[lyricsEntry];
                                     if (!tieStartNote.ParentVoiceEntry.LyricsEntries[lyricsEntry] === undefined) {
@@ -768,95 +773,95 @@ export class VoiceGenerator {
                                         val.Parent = tieStartNote.ParentVoiceEntry;
                                     }
                                 }
-                                this.openTieDict.Remove(tieNumber);
+                                delete this.openTieDict[tieNumber];
                             }
                         }
                     }
                     catch (err) {
-                        var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TieError", "Error while reading tie.");
+                        let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/TieError", "Error while reading tie.");
                         this.musicSheet.SheetErrors.pushTemp(errorMsg);
                     }
 
                 }
             }
-            else if (tieNodeList.length() == 2) {
-                var tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
+            else if (tieNodeList.length === 2) {
+                let tieNumber: number = this.findCurrentNoteInTieDict(this.currentNote);
                 if (tieNumber >= 0) {
-                    var tie: Tie = this.openTieDict[tieNumber];
-                    var tieStartNote: Note = tie.Start;
+                    let tie: Tie = this.openTieDict[tieNumber];
+                    let tieStartNote: Note = tie.Start;
                     tieStartNote.Length.Add(this.currentNote.Length);
                     tie.Fractions.push(this.currentNote.Length);
-                    if (this.currentNote.NoteBeam != null) {
-                        var noteBeamIndex: number = this.currentNote.NoteBeam.Notes.indexOf(this.currentNote);
-                        if (noteBeamIndex == 0 && tie.BeamStartTimestamp == null)
+                    if (this.currentNote.NoteBeam !== undefined) {
+                        let noteBeamIndex: number = this.currentNote.NoteBeam.Notes.indexOf(this.currentNote);
+                        if (noteBeamIndex === 0 && tie.BeamStartTimestamp === undefined)
                             tie.BeamStartTimestamp = measureStartAbsoluteTimestamp + this.currentVoiceEntry.Timestamp;
-                        var noteBeam: Beam = this.currentNote.NoteBeam;
+                        let noteBeam: Beam = this.currentNote.NoteBeam;
                         noteBeam.Notes[noteBeamIndex] = tieStartNote;
                         tie.TieBeam = noteBeam;
                     }
-                    for (var idx: number = 0, len = this.currentNote.NoteSlurs.length; idx < len; ++idx) {
-                        var slur: Slur = this.currentNote.NoteSlurs[idx];
-                        if (slur.StartNote == this.currentNote) {
+                    for (let idx: number = 0, len = this.currentNote.NoteSlurs.length; idx < len; ++idx) {
+                        let 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) {
+                        if (slur.EndNote === this.currentNote) {
                             slur.EndNote = tie.Start;
                             slur.EndNote.NoteSlurs.push(slur);
                         }
                     }
-                    var lyricsEntries: KeyValuePair<number, LyricsEntry>[] = this.currentVoiceEntry.LyricsEntries.ToArray();
-                    for (var idx: number = 0, len = lyricsEntries.length; idx < len; ++idx) {
-                        var lyricsEntry: KeyValuePair<number, LyricsEntry> = lyricsEntries[idx];
-                        if (!tieStartNote.ParentVoiceEntry.LyricsEntries.ContainsKey(lyricsEntry.Key)) {
-                            tieStartNote.ParentVoiceEntry.LyricsEntries.push(lyricsEntry.Key, lyricsEntry.Value);
-                            lyricsEntry.Value.Parent = tieStartNote.ParentVoiceEntry;
+                    let lyricsEntries: { [_: number]: LyricsEntry; } = this.currentVoiceEntry.LyricsEntries;
+                    for (let key in lyricsEntries) {
+                        let lyricsEntry: LyricsEntry = lyricsEntries[key];
+                        if (tieStartNote.ParentVoiceEntry.LyricsEntries[key] === undefined) {
+                            tieStartNote.ParentVoiceEntry.LyricsEntries[key] = lyricsEntry;
+                            lyricsEntry.Parent = tieStartNote.ParentVoiceEntry;
                         }
                     }
                     if (maxTieNoteFraction < this.currentStaffEntry.Timestamp + this.currentNote.Length)
                         maxTieNoteFraction = this.currentStaffEntry.Timestamp + this.currentNote.Length;
-                    this.currentVoiceEntry.Notes.Remove(this.currentNote);
+                    delete this.currentVoiceEntry.Notes[this.currentNote];
                 }
             }
         }
     }
     private getNextAvailableNumberForTie(): number {
-        var keys: number[] = this.openTieDict.keys();
-        if (keys.length == 0)
+        let keys: string[] = Object.keys(this.openTieDict);
+        if (keys.length === 0)
             return 1;
-        keys.Sort();
-        for (var i: number = 0; i < keys.length; i++) {
-            if (i + 1 != keys[i])
+        keys.sort((a, b) => (a - b)); // FIXME Andrea: test
+        for (let i: number = 0; i < keys.length; i++) {
+            if (<string>(i + 1) !== keys[i])
                 return i + 1;
         }
         return keys[keys.length - 1] + 1;
     }
     private findCurrentNoteInTieDict(candidateNote: Note): number {
-        var openTieDictArr: KeyValuePair<number, Tie>[] = this.openTieDict.ToArray();
-        for (var idx: number = 0, len = openTieDictArr.length; idx < len; ++idx) {
-            var keyValuePair: KeyValuePair<number, Tie> = openTieDictArr[idx];
-            if (keyValuePair.Value.Start.Pitch.FundamentalNote == candidateNote.Pitch.FundamentalNote && keyValuePair.Value.Start.Pitch.Octave == candidateNote.Pitch.Octave) {
-                return keyValuePair.Key;
+        let openTieDict: { [_: number]: Tie; } = this.openTieDict;
+        for (let key in openTieDict) {
+            let tie: Tie = openTieDict[key];
+            if (tie.Start.Pitch.FundamentalNote === candidateNote.Pitch.FundamentalNote && tie.Start.Pitch.Octave === candidateNote.Pitch.Octave) {
+                return key;
             }
         }
         return -1;
     }
     private getTupletNoteDurationFromType(xmlNode: IXmlElement): Fraction {
-        if (xmlNode.Element("type") != null) {
-            var typeNode: IXmlElement = xmlNode.Element("type");
-            if (typeNode != null) {
-                var type: string = typeNode.Value;
+        if (xmlNode.Element("type") !== undefined) {
+            let typeNode: IXmlElement = xmlNode.Element("type");
+            if (typeNode !== undefined) {
+                let type: string = typeNode.Value;
                 try {
                     return this.getNoteDurationFromType(type);
                 }
                 catch (e) {
-                    var errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError", "Invalid note duration.");
+                    let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/NoteDurationError", "Invalid note duration.");
                     this.musicSheet.SheetErrors.pushTemp(errorMsg);
                     throw new MusicSheetReadingException("", e);
                 }
 
             }
         }
-        return null;
+        return undefined;
     }
 }

+ 4 - 0
src/Util/collectionUtil.ts

@@ -9,4 +9,8 @@ export class CollectionUtil {
 
         return false;
     }
+
+    public static last(array: any[]): any {
+        return array[array.length - 1];
+    }
 }