Explorar el Código

Fixing Fractions and stuff

Andrea Condoluci hace 9 años
padre
commit
9311a382d5

+ 1 - 1
src/MusicalScore/MusicSource/MappingSourceMusicPart.ts

@@ -6,7 +6,7 @@ import {PartListEntry} from "./PartListEntry";
 export class MappingSourceMusicPart /* implements IComparable, IComparable<MappingSourceMusicPart>*/ {
     constructor(
         sourceMusicPart: SourceMusicPart, startTimestamp: Fraction, parentPartListEntry?: Repetition,
-        repetitionRun: number = -1, isEnding: boolean = false,
+        repetitionRun: number = -1, isEnding: boolean = false
     ) {
         this.sourceMusicPart = sourceMusicPart;
         this.parentPartListEntry = parentPartListEntry;

+ 14 - 25
src/MusicalScore/ScoreIO/InstrumentReader.ts

@@ -250,7 +250,7 @@ export class InstrumentReader {
                 this.musicSheet.SheetErrors.push(errorMsg + this.instrument.Name);
               } else {
                 divisionsException = true;
-                throw new MusicSheetReadingException(errorMsg + this.instrument.Name, 0);
+                throw new MusicSheetReadingException(errorMsg + this.instrument.Name);
               }
             }
 
@@ -266,7 +266,7 @@ export class InstrumentReader {
               this.musicSheet.SheetErrors.push(errorMsg + this.instrument.Name);
             } else {
               divisionsException = true;
-              throw new MusicSheetReadingException(errorMsg + this.instrument.Name, 0);
+              throw new MusicSheetReadingException(errorMsg + this.instrument.Name);
             }
           }
           this.addAbstractInstruction(xmlNode, guitarPro);
@@ -358,7 +358,7 @@ export class InstrumentReader {
       }
     } catch (e) {
       if (divisionsException) {
-        throw new MusicSheetReadingException(e.Message, 0);
+        throw new MusicSheetReadingException(e.Message);
       }
       let errorMsg: string = ITextTranslation.translateText("ReaderErrorMessages/MeasureError", "Error while reading Measure.");
       this.musicSheet.SheetErrors.pushTemp(errorMsg);
@@ -697,7 +697,7 @@ export class InstrumentReader {
           logging.debug("InstrumentReader.addAbstractInstruction", errorMsg, ex);
         }
 
-        if ((num === denom === 4) || (num === denom === 2)) {
+        if ((num === 4 && denom === 4) || (num === 2 && denom === 2)) {
           symbolEnum = RhythmSymbolEnum.NONE;
         }
         this.abstractInstructions[1] = new RhythmInstruction(
@@ -850,23 +850,23 @@ export class InstrumentReader {
   }
   */
   private saveClefInstructionAtEndOfMeasure(): void {
-    for (let key of this.abstractInstructions) {
+    for (let key in this.abstractInstructions) {
       let value = this.abstractInstructions[key];
       if (value instanceof ClefInstruction) {
         let clefInstruction: ClefInstruction = <ClefInstruction>value;
         if (
-          (this.activeClefs[key - 1] === undefined) ||
-          (clefInstruction.ClefType !== this.activeClefs[key - 1].ClefType || (
-            clefInstruction.ClefType === this.activeClefs[key - 1].ClefType &&
-            clefInstruction.Line !== this.activeClefs[key - 1].Line
+          (this.activeClefs[+key - 1] === undefined) ||
+          (clefInstruction.ClefType !== this.activeClefs[+key - 1].ClefType || (
+            clefInstruction.ClefType === this.activeClefs[+key - 1].ClefType &&
+            clefInstruction.Line !== this.activeClefs[+key - 1].Line
           ))) {
           let lastStaffEntry: SourceStaffEntry = new SourceStaffEntry(undefined, undefined);
-          this.currentMeasure.LastInstructionsStaffEntries[this.inSourceMeasureInstrumentIndex + key - 1] = lastStaffEntry;
+          this.currentMeasure.LastInstructionsStaffEntries[this.inSourceMeasureInstrumentIndex + (+key) - 1] = lastStaffEntry;
           let newClefInstruction: ClefInstruction = clefInstruction;
           newClefInstruction.Parent = lastStaffEntry;
           lastStaffEntry.Instructions.push(newClefInstruction);
-          this.activeClefs[key - 1] = clefInstruction;
-          delete this.abstractInstructions[key]; // FIXME Andrea: might hurt performance
+          this.activeClefs[+key - 1] = clefInstruction;
+          delete this.abstractInstructions[+key]; // FIXME Andrea: might hurt performance?
         }
       }
     }
@@ -883,7 +883,7 @@ export class InstrumentReader {
           if (actualNotes !== undefined && normalNotes !== undefined) {
             let actual: number = parseInt(actualNotes.Value);
             let normal: number = parseInt(normalNotes.Value);
-            duration = new Fraction(normal, actual) * typeDuration;
+            duration = new Fraction(normal * typeDuration.Numerator, actual * typeDuration.Denominator);
           }
         }
       }
@@ -989,21 +989,10 @@ export class InstrumentReader {
         xmlMeasureIndex++;
         if (xmlMeasureIndex === this.xmlMeasureList.length) {
           let errorMsg: string = ITextTranslation.translateText("ReaderErrorMEssages/DivisionsError", "Invalid divisions value at Instrument: ");
-          throw new MusicSheetReadingException(errorMsg + this.instrument.Name, 0);
+          throw new MusicSheetReadingException(errorMsg + this.instrument.Name);
         }
       }
     }
     return divisionsFromNote;
   }
 }
-
-/*
-class KeyValuePairClass<T, TU> {
-  constructor(key: T, value: TU) {
-    this.key = key;
-    this.value = value;
-  }
-  public key: T;
-  public value: TU;
-}
-*/

+ 6 - 8
src/MusicalScore/ScoreIO/MusicSheetReader.ts

@@ -18,7 +18,6 @@ import {SubInstrument} from "../SubInstrument";
 import {MidiInstrument} from "../VoiceData/Instructions/ClefInstruction";
 import {AbstractNotationInstruction} from "../VoiceData/Instructions/AbstractNotationInstruction";
 
-type IPhonicScoreInterface = any;
 type RepetitionInstructionReader = any;
 
 export class MusicSheetReader /*implements IMusicSheetReader*/ {
@@ -33,7 +32,6 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
   //  this.repetitionCalculator = MusicSymbolModuleFactory.createRepetitionCalculator();
   //}
 
-  private phonicScoreInterface: IPhonicScoreInterface;
   private repetitionInstructionReader: RepetitionInstructionReader;
   // private repetitionCalculator: RepetitionCalculator;
   // private afterSheetReadingModules: IAfterSheetReadingModule[];
@@ -245,18 +243,18 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
       }
     }
     if (rhythmInstructions.length > 0 && rhythmInstructions.length < this.completeNumberOfStaves) {
-      let rhythmInstruction: RhythmInstruction = new RhythmInstruction(rhythmInstructions[index]);
+      let rhythmInstruction: RhythmInstruction = rhythmInstructions[index].clone();
       for (let i: number = 0; i < this.completeNumberOfStaves; i++) {
         if (
           this.currentMeasure.FirstInstructionsStaffEntries[i] !== undefined &&
           !(this._lastElement(this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions) instanceof RhythmInstruction)
         ) {
           this.currentMeasure.FirstInstructionsStaffEntries[i].removeAllInstructionsOfType<RhythmInstruction>();
-          this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.push(new RhythmInstruction(rhythmInstruction));
+          this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.push(rhythmInstruction.clone());
         }
         if (this.currentMeasure.FirstInstructionsStaffEntries[i] === undefined) {
           this.currentMeasure.FirstInstructionsStaffEntries[i] = new SourceStaffEntry(undefined, undefined);
-          this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.push(new RhythmInstruction(rhythmInstruction));
+          this.currentMeasure.FirstInstructionsStaffEntries[i].Instructions.push(rhythmInstruction.clone());
         }
       }
       for (let idx: number = 0, len: number = instrumentReaders.length; idx < len; ++idx) {
@@ -285,7 +283,7 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
         if (this._lastElement(this.currentMeasure.FirstInstructionsStaffEntries[rhythmInstructions.indexOf(rhythmInstruction)].Instructions) instanceof RhythmInstruction) {
           // TODO Test correctness
           let instrs: AbstractNotationInstruction[] = this.currentMeasure.FirstInstructionsStaffEntries[rhythmInstructions.indexOf(rhythmInstruction)].Instructions;
-          instrs[instrs.length - 1] = new RhythmInstruction(rhythmInstructions[index]);
+          instrs[instrs.length - 1] = rhythmInstructions[index].clone();
         }
       }
       if (
@@ -368,7 +366,7 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
   private checkIfMeasureIsImplicit(maxInstrumentDuration: Fraction, activeRhythm: Fraction): boolean {
     if (this.previousMeasure === undefined && maxInstrumentDuration < activeRhythm) { return true; }
     if (this.previousMeasure !== undefined) {
-      return (this.previousMeasure.Duration + maxInstrumentDuration === activeRhythm);
+      return Fraction.plus(this.previousMeasure.Duration, maxInstrumentDuration).CompareTo(activeRhythm) === 0;
     }
     return false;
   }
@@ -616,7 +614,7 @@ export class MusicSheetReader /*implements IMusicSheetReader*/ {
         let node: IXmlElement = entryArray[idx];
         if (node.Name === "score-part") {
           let instrIdString: string = node.Attribute("id").Value;
-          let instrument: Instrument = new Instrument(instrumentId, instrIdString, this.phonicScoreInterface, this.musicSheet, currentGroup);
+          let instrument: Instrument = new Instrument(instrumentId, instrIdString, this.musicSheet, currentGroup);
           instrumentId++;
           let partElements: IXmlElement[] = node.Elements();
           for (let idx2: number = 0, len2: number = partElements.length; idx2 < len2; ++idx2) {

+ 19 - 20
src/MusicalScore/ScoreIO/VoiceGenerator.ts

@@ -174,15 +174,11 @@ export class VoiceGenerator {
             this.handleOpenBeam();
     }
     public checkOpenTies(): void {
-        let toRemove: number[] = [];
-        let openTieDict: {[_: number]: Tie} = this.openTieDict;
+        let openTieDict: {[key: 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 (let key of toRemove) {
-            delete openTieDict[key];
+                delete openTieDict[key];
         }
     }
     public hasVoiceEntry(): boolean {
@@ -712,7 +708,7 @@ export class VoiceGenerator {
                             this.openTieDict[newTieNumber] = tie;
                             if (this.currentNote.NoteBeam !== undefined)
                                 if (this.currentNote.NoteBeam.Notes[0] === this.currentNote) {
-                                    tie.BeamStartTimestamp = measureStartAbsoluteTimestamp + this.currentVoiceEntry.Timestamp;
+                                    tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
                                 }
                                 else {
                                     for (let idx: number = 0, len = this.currentNote.NoteBeam.Notes.length; idx < len; ++idx) {
@@ -723,7 +719,7 @@ export class VoiceGenerator {
                                         }
                                     }
                                     if (this.currentNote === CollectionUtil.last(this.currentNote.NoteBeam.Notes))
-                                        tie.BeamStartTimestamp = measureStartAbsoluteTimestamp + this.currentVoiceEntry.Timestamp;
+                                        tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
                                 }
                         }
                         else if (type === "stop") {
@@ -734,15 +730,16 @@ export class VoiceGenerator {
                                 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;
-                                delete this.currentVoiceEntry.Notes[this.currentNote];
+                                if (maxTieNoteFraction.lt(Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length)))
+                                    maxTieNoteFraction = Fraction.plus(this.currentStaffEntry.Timestamp, this.currentNote.Length);
+                                let i: number = this.currentVoiceEntry.Notes.indexOf(this.currentNote);
+                                if (i !== -1) delete this.currentVoiceEntry.Notes[i];
                                 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) {
                                     let noteBeamIndex: number = this.currentNote.NoteBeam.Notes.indexOf(this.currentNote);
                                     if (noteBeamIndex === 0 && tie.BeamStartTimestamp === undefined)
-                                        tie.BeamStartTimestamp = measureStartAbsoluteTimestamp + this.currentVoiceEntry.Timestamp;
+                                        tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
                                     let noteBeam: Beam = this.currentNote.NoteBeam;
                                     noteBeam.Notes[noteBeamIndex] = tieStartNote;
                                     tie.TieBeam = noteBeam;
@@ -794,7 +791,7 @@ export class VoiceGenerator {
                     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;
+                            tie.BeamStartTimestamp = Fraction.plus(measureStartAbsoluteTimestamp, this.currentVoiceEntry.Timestamp);
                         let noteBeam: Beam = this.currentNote.NoteBeam;
                         noteBeam.Notes[noteBeamIndex] = tieStartNote;
                         tie.TieBeam = noteBeam;
@@ -818,9 +815,11 @@ export class VoiceGenerator {
                             lyricsEntry.Parent = tieStartNote.ParentVoiceEntry;
                         }
                     }
-                    if (maxTieNoteFraction < this.currentStaffEntry.Timestamp + this.currentNote.Length)
-                        maxTieNoteFraction = this.currentStaffEntry.Timestamp + this.currentNote.Length;
-                    delete this.currentVoiceEntry.Notes[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:
+                    let i: number = this.currentVoiceEntry.Notes.indexOf(this.currentNote);
+                    if (i !== -1) delete this.currentVoiceEntry.Notes[i];
                 }
             }
         }
@@ -829,19 +828,19 @@ export class VoiceGenerator {
         let keys: string[] = Object.keys(this.openTieDict);
         if (keys.length === 0)
             return 1;
-        keys.sort((a, b) => (a - b)); // FIXME Andrea: test
+        keys.sort((a, b) => (+a - +b)); // FIXME Andrea: test
         for (let i: number = 0; i < keys.length; i++) {
-            if (<string>(i + 1) !== keys[i])
+            if ("" + (i + 1) !== keys[i])
                 return i + 1;
         }
-        return keys[keys.length - 1] + 1;
+        return +(keys[keys.length - 1]) + 1;
     }
     private findCurrentNoteInTieDict(candidateNote: Note): number {
         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 +key;
             }
         }
         return -1;

+ 8 - 7
src/MusicalScore/SubInstrument.ts

@@ -5,8 +5,8 @@ export class SubInstrument {
     constructor(parentInstrument: Instrument) {
         this.parentInstrument = parentInstrument;
         this.FixedKey = -1;
-        this.MidiInstrumentId = this.parseMidiInstrument(this.parentInstrument.Name);
-        this.Name = SubInstrument.midiInstrument[this.MidiInstrumentId];
+        this.Name = this.parseMidiInstrument(this.parentInstrument.Name);
+        this.MidiInstrumentId = SubInstrument.midiInstrument[this.Name];
         this.Volume = 1.0;
     }
     private static midiInstrument: { [key: string]: MidiInstrument; } = {
@@ -84,16 +84,17 @@ export class SubInstrument {
           || instrument === MidiInstrument.Electric_Piano_2);
     }
     public setMidiInstrument(instrumentType: string): void {
-        this.MidiInstrumentId = this.parseMidiInstrument(instrumentType);
+        this.MidiInstrumentId = SubInstrument.midiInstrument[this.parseMidiInstrument(instrumentType)];
     }
-    private parseMidiInstrument(instrumentType: string): MidiInstrument {
+
+    private parseMidiInstrument(instrumentType: string): string {
         // FIXME: test this function
         try {
             if (instrumentType) {
                 let tmpName: string = instrumentType.toLowerCase().trim();
                 for (let key in SubInstrument.midiInstrument) {
                     if (tmpName.indexOf(key) !== -1) {
-                        return SubInstrument.midiInstrument[key];
+                        return key;
                     }
                 }
             }
@@ -101,13 +102,13 @@ export class SubInstrument {
                 let tmpName: string = this.parentInstrument.Name.toLowerCase().trim();
                 for (let key in SubInstrument.midiInstrument) {
                     if (tmpName.indexOf(key) !== -1) {
-                        return SubInstrument.midiInstrument[key];
+                        return key;
                     }
                 }
             }
         } catch (e) {
             console.log("Error parsing MIDI Instrument. Default to Grand Piano."); // FIXME
         }
-        return MidiInstrument.Acoustic_Grand_Piano;
+        return "unnamed";
     }
 }

+ 3 - 2
src/MusicalScore/VoiceData/Expressions/ContinuousExpressions/continuousDynamicExpression.ts

@@ -12,6 +12,7 @@ export class ContinuousDynamicExpression extends AbstractExpression {
     //    this.setType();
     //}
     constructor(dynamicType: ContDynamicEnum, placement: PlacementEnum, staffNumber: number, label: string) {
+        super();
         this.dynamicType = dynamicType;
         this.label = label;
         this.placement = placement;
@@ -94,13 +95,13 @@ export class ContinuousDynamicExpression extends AbstractExpression {
         if (this.EndMultiExpression != null)
             continuousAbsoluteEndTimestamp = this.EndMultiExpression.AbsoluteTimestamp;
         else {
-            continuousAbsoluteEndTimestamp = this.startMultiExpression.SourceMeasureParent.AbsoluteTimestamp + this.startMultiExpression.SourceMeasureParent.Duration;
+            continuousAbsoluteEndTimestamp = Fraction.plus(this.startMultiExpression.SourceMeasureParent.AbsoluteTimestamp, this.startMultiExpression.SourceMeasureParent.Duration);
         }
         if (currentAbsoluteTimestamp < continuousAbsoluteStartTimestamp)
             return -1;
         if (currentAbsoluteTimestamp > continuousAbsoluteEndTimestamp)
             return -2;
-        var interpolationRatio: number = (currentAbsoluteTimestamp - continuousAbsoluteStartTimestamp).RealValue / (continuousAbsoluteEndTimestamp - continuousAbsoluteStartTimestamp).RealValue;
+        var interpolationRatio: number = Fraction.minus(currentAbsoluteTimestamp, continuousAbsoluteStartTimestamp).RealValue / Fraction.minus(continuousAbsoluteEndTimestamp, continuousAbsoluteStartTimestamp).RealValue;
         var interpolatedVolume: number = Math.max(0.0, Math.min(99.9, this.startVolume + (this.endVolume - this.startVolume) * interpolationRatio));
         return <number>interpolatedVolume;
     }

+ 9 - 5
src/MusicalScore/VoiceData/Expressions/ContinuousExpressions/continuousTempoExpression.ts

@@ -5,12 +5,15 @@ import {AbstractTempoExpression} from "../abstractTempoExpression";
 
 export class ContinuousTempoExpression extends AbstractTempoExpression {
     constructor(label: string, placement: PlacementEnum, staffNumber: number, parentMultiTempoExpression: MultiTempoExpression) {
-        super.label = label;
-        super.placement = placement;
-        super.staffNumber = staffNumber;
-        super.parentMultiTempoExpression = parentMultiTempoExpression;
+        super(label, placement, staffNumber, parentMultiTempoExpression);
+        //super.label = label;
+        //super.placement = placement;
+        //super.staffNumber = staffNumber;
+        //super.parentMultiTempoExpression = parentMultiTempoExpression;
+
         this.setTempoType();
     }
+
     private absoluteEndTimestamp: Fraction;
     private tempoType: ContinuousTempoType;
     private startTempo: number;
@@ -84,6 +87,7 @@ export class ContinuousTempoExpression extends AbstractTempoExpression {
         else return false;
     }
 }
+
 export enum ContinuousTempoType {
     accelerando = 0,
     stretto = 1,
@@ -100,4 +104,4 @@ export enum ContinuousTempoType {
     ritenuto = 12,
     rubato = 13,
     precipitando = 14
-}
+}

+ 14 - 7
src/MusicalScore/VoiceData/Expressions/abstractTempoExpression.ts

@@ -1,10 +1,18 @@
 import {PlacementEnum} from "./abstractExpression";
 import {MultiTempoExpression} from "./multiTempoExpression";
+
 export class AbstractTempoExpression {
+    constructor(label: string, placement: PlacementEnum, staffNumber: number, parentMultiTempoExpression: MultiTempoExpression) {
+        this.label = label;
+        this.placement = placement;
+        this.staffNumber = staffNumber;
+        this.parentMultiTempoExpression = parentMultiTempoExpression;
+    }
     protected label: string;
     protected placement: PlacementEnum;
     protected staffNumber: number;
     protected parentMultiTempoExpression: MultiTempoExpression;
+
     public get Label(): string {
         return this.label;
     }
@@ -26,17 +34,16 @@ export class AbstractTempoExpression {
     public get ParentMultiTempoExpression(): MultiTempoExpression {
         return this.parentMultiTempoExpression;
     }
-    protected static isStringInStringList(wordsToFind: Array<string>, inputString: string): boolean {
-        for (var idx: number = 0, len = wordsToFind.length; idx < len; ++idx) {
-            var wordToFind: string = wordsToFind[idx];
-            if (AbstractTempoExpression.stringContainsSeparatedWord(inputString.toLowerCase().Trim(), wordToFind.toLowerCase().Trim()))
+
+    protected static isStringInStringList(wordsToFind: string[], inputString: string): boolean {
+        for (let wordToFind of wordsToFind) {
+            if (AbstractTempoExpression.stringContainsSeparatedWord(inputString.toLowerCase().trim(), wordToFind.toLowerCase().trim())) {
                 return true;
+            }
         }
         return false;
     }
     private static stringContainsSeparatedWord(str: string, word: string): boolean {
-        if (str == word || str.Contains(" " + word) || str.Contains(word + " "))
-            return true;
-        return false;
+        return (str === word || str.indexOf(" " + word) !== -1 || str.indexOf(word + " ") !== -1);
     }
 }

+ 1 - 1
src/MusicalScore/VoiceData/Expressions/instantaniousDynamicExpression.ts

@@ -7,6 +7,7 @@ import {logging} from "../../../Common/logging";
 
 export class InstantaniousDynamicExpression extends AbstractExpression {
     constructor(dynamicExpression: string, soundDynamics: number, placement: PlacementEnum, staffNumber: number) {
+        super();
         this.dynamicEnum = DynamicEnum[dynamicExpression.toLowerCase()];
         this.soundDynamic = soundDynamics;
         this.placement = placement;
@@ -93,7 +94,6 @@ export class InstantaniousDynamicExpression extends AbstractExpression {
     }
     public static isInputStringInstantaniousDynamic(inputString:string): boolean {
         if (inputString === null) { return false; }
-            return false;
         return (InstantaniousDynamicExpression.listInstantaniousDynamics.indexOf(inputString) !== -1);
     }
 

+ 3 - 6
src/MusicalScore/VoiceData/Expressions/instantaniousTempoExpression.ts

@@ -6,10 +6,7 @@ import {MultiTempoExpression} from "./multiTempoExpression";
 
 export class InstantaniousTempoExpression extends AbstractTempoExpression {
     constructor(label: string, placement: PlacementEnum, staffNumber: number, soundTempo: number, parentMultiTempoExpression: MultiTempoExpression) {
-        super.label = label;
-        super.placement = placement;
-        super.staffNumber = staffNumber;
-        super.parentMultiTempoExpression = parentMultiTempoExpression;
+        super(label, placement, staffNumber, parentMultiTempoExpression);
         this.setTempoAndTempoType(soundTempo);
     }
     
@@ -187,10 +184,10 @@ export class InstantaniousTempoExpression extends AbstractTempoExpression {
         return this.parentMultiTempoExpression;
     }
     public getAbsoluteTimestamp(): Fraction {
-        return (this.ParentMultiTempoExpression.SourceMeasureParent.AbsoluteTimestamp + this.ParentMultiTempoExpression.Timestamp);
+        return Fraction.plus(this.ParentMultiTempoExpression.SourceMeasureParent.AbsoluteTimestamp, this.ParentMultiTempoExpression.Timestamp);
     }
     public getAbsoluteFloatTimestamp(): number {
-        return (this.ParentMultiTempoExpression.SourceMeasureParent.AbsoluteTimestamp + this.ParentMultiTempoExpression.Timestamp).RealValue;
+        return Fraction.plus(this.ParentMultiTempoExpression.SourceMeasureParent.AbsoluteTimestamp, this.ParentMultiTempoExpression.Timestamp).RealValue;
     }
     public static getDefaultValueForTempoType(tempoEnum: TempoEnum): number {
         switch (tempoEnum) {

+ 1 - 0
src/MusicalScore/VoiceData/Expressions/moodExpression.ts

@@ -2,6 +2,7 @@ import {PlacementEnum, AbstractExpression} from "./abstractExpression";
 
 export class MoodExpression extends AbstractExpression {
     constructor(label: string, placement: PlacementEnum, staffNumber: number) {
+        super();
         this.label = label;
         this.placement = placement;
         this.staffNumber = staffNumber;

+ 54 - 43
src/MusicalScore/VoiceData/Expressions/multiExpression.ts

@@ -1,5 +1,14 @@
-export class MultiExpression implements IComparable<MultiExpression>
-{
+import {SourceMeasure} from "../SourceMeasure";
+import {Fraction} from "../../../Common/DataObjects/fraction";
+import {InstantaniousDynamicExpression} from "./instantaniousDynamicExpression";
+import {ContinuousDynamicExpression} from "./ContinuousExpressions/continuousDynamicExpression";
+import {OctaveShift} from "./ContinuousExpressions/octaveShift";
+import {MoodExpression} from "./moodExpression";
+import {UnknownExpression} from "./unknownExpression";
+import {AbstractExpression} from "./abstractExpression";
+import {PlacementEnum} from "./abstractExpression";
+
+export class MultiExpression /*implements IComparable<MultiExpression>*/ {
     constructor(sourceMeasure: SourceMeasure, timestamp: Fraction) {
         this.sourceMeasure = sourceMeasure;
         this.timestamp = timestamp;
@@ -10,12 +19,13 @@ export class MultiExpression implements IComparable<MultiExpression>
     private instantaniousDynamic: InstantaniousDynamicExpression;
     private endingContinuousDynamic: ContinuousDynamicExpression;
     private startingContinuousDynamic: ContinuousDynamicExpression;
-    private unknownList: List<UnknownExpression> = new List<UnknownExpression>();
-    private moodList: List<MoodExpression> = new List<MoodExpression>();
-    private expressions: List<MultiExpressionEntry> = new List<MultiExpressionEntry>();
+    private unknownList: UnknownExpression[] = [];
+    private moodList: MoodExpression[] = [];
+    private expressions: MultiExpressionEntry[] = [];
     private combinedExpressionsText: string;
     private octaveShiftStart: OctaveShift;
     private octaveShiftEnd: OctaveShift;
+    
     public get SourceMeasureParent(): SourceMeasure {
         return this.sourceMeasure;
     }
@@ -35,7 +45,7 @@ export class MultiExpression implements IComparable<MultiExpression>
         this.timestamp = value;
     }
     public get AbsoluteTimestamp(): Fraction {
-        return this.timestamp + this.sourceMeasure.AbsoluteTimestamp;
+        return Fraction.plus(this.timestamp, this.sourceMeasure.AbsoluteTimestamp);
     }
     public get InstantaniousDynamic(): InstantaniousDynamicExpression {
         return this.instantaniousDynamic;
@@ -55,13 +65,13 @@ export class MultiExpression implements IComparable<MultiExpression>
     public set StartingContinuousDynamic(value: ContinuousDynamicExpression) {
         this.startingContinuousDynamic = value;
     }
-    public get MoodList(): List<MoodExpression> {
+    public get MoodList():  MoodExpression[] {
         return this.moodList;
     }
-    public get UnknownList(): List<UnknownExpression> {
+    public get UnknownList():  UnknownExpression[] {
         return this.unknownList;
     }
-    public get EntriesList(): List<MultiExpressionEntry> {
+    public get EntriesList():  MultiExpressionEntry[] {
         return this.expressions;
     }
     public get OctaveShiftStart(): OctaveShift {
@@ -84,7 +94,7 @@ export class MultiExpression implements IComparable<MultiExpression>
     }
     public getPlacementOfFirstEntry(): PlacementEnum {
         var placement: PlacementEnum = PlacementEnum.Above;
-        if (this.expressions.Count > 0) {
+        if (this.expressions.length > 0) {
             if (this.expressions[0].expression instanceof InstantaniousDynamicExpression)
                 placement = (<InstantaniousDynamicExpression>(this.expressions[0].expression)).Placement;
             else if (this.expressions[0].expression instanceof ContinuousDynamicExpression)
@@ -96,37 +106,38 @@ export class MultiExpression implements IComparable<MultiExpression>
         }
         return placement;
     }
-    public getFontstyleOfFirstEntry(): PSFontStyles {
-        var fontStyle: PSFontStyles = PSFontStyles.Regular;
-        if (this.expressions.Count > 0) {
-            if (this.expressions[0].expression instanceof ContinuousDynamicExpression)
-                fontStyle = PSFontStyles.Italic;
-            else if (this.expressions[0].expression instanceof MoodExpression)
-                fontStyle = PSFontStyles.Italic;
-            else if (this.expressions[0].expression instanceof UnknownExpression)
-                fontStyle = PSFontStyles.Regular;
-        }
-        return fontStyle;
-    }
-    public getFirstEntry(staffLine: StaffLine, graphLabel: GraphicalLabel): AbstractGraphicalExpression {
-        var indexOfFirstNotInstDynExpr: number = 0;
-        if (this.expressions[0].expression instanceof InstantaniousDynamicExpression)
-            indexOfFirstNotInstDynExpr = 1;
-        if (this.expressions.Count > 0) {
-            if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof ContinuousDynamicExpression)
-                return new GraphicalContinuousDynamicExpression(<ContinuousDynamicExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphLabel);
-            else if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof MoodExpression)
-                return new GraphicalMoodExpression(<MoodExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphLabel);
-            else if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof UnknownExpression)
-                return new GraphicalUnknownExpression(<UnknownExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphLabel);
-            else return null;
-        }
-        else return null;
-    }
+    // (*)
+    //public getFontstyleOfFirstEntry(): PSFontStyles {
+    //    var fontStyle: PSFontStyles = PSFontStyles.Regular;
+    //    if (this.expressions.length > 0) {
+    //        if (this.expressions[0].expression instanceof ContinuousDynamicExpression)
+    //            fontStyle = PSFontStyles.Italic;
+    //        else if (this.expressions[0].expression instanceof MoodExpression)
+    //            fontStyle = PSFontStyles.Italic;
+    //        else if (this.expressions[0].expression instanceof UnknownExpression)
+    //            fontStyle = PSFontStyles.Regular;
+    //    }
+    //    return fontStyle;
+    //}
+    //public getFirstEntry(staffLine: StaffLine, graphLabel: GraphicalLabel): AbstractGraphicalExpression {
+    //    var indexOfFirstNotInstDynExpr: number = 0;
+    //    if (this.expressions[0].expression instanceof InstantaniousDynamicExpression)
+    //        indexOfFirstNotInstDynExpr = 1;
+    //    if (this.expressions.length > 0) {
+    //        if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof ContinuousDynamicExpression)
+    //            return new GraphicalContinuousDynamicExpression(<ContinuousDynamicExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphLabel);
+    //        else if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof MoodExpression)
+    //            return new GraphicalMoodExpression(<MoodExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphLabel);
+    //        else if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof UnknownExpression)
+    //            return new GraphicalUnknownExpression(<UnknownExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphLabel);
+    //        else return null;
+    //    }
+    //    else return null;
+    //}
     public addExpression(abstractExpression: AbstractExpression, prefix: string): void {
         if (abstractExpression instanceof InstantaniousDynamicExpression) {
             if (this.instantaniousDynamic != null)
-                removeExpressionFromEntryList(this.InstantaniousDynamic);
+                this.removeExpressionFromEntryList(this.InstantaniousDynamic);
             this.instantaniousDynamic = <InstantaniousDynamicExpression>abstractExpression;
             this.instantaniousDynamic.ParentMultiExpression = this;
         }
@@ -134,10 +145,10 @@ export class MultiExpression implements IComparable<MultiExpression>
             this.startingContinuousDynamic = <ContinuousDynamicExpression>abstractExpression;
         }
         else if (abstractExpression instanceof MoodExpression) {
-            this.moodList.Add(<MoodExpression>abstractExpression);
+            this.moodList.push(<MoodExpression>abstractExpression);
         }
         else if (abstractExpression instanceof UnknownExpression) {
-            this.unknownList.Add(<UnknownExpression>abstractExpression);
+            this.unknownList.push(<UnknownExpression>abstractExpression);
         }
         this.addExpressionToEntryList(abstractExpression, prefix);
     }
@@ -165,13 +176,13 @@ export class MultiExpression implements IComparable<MultiExpression>
         else if (expression instanceof UnknownExpression)
             multiExpressionEntry.label = (<UnknownExpression>(expression)).Label;
         else multiExpressionEntry.label = "";
-        this.expressions.Add(multiExpressionEntry);
+        this.expressions.push(multiExpressionEntry);
     }
     private removeExpressionFromEntryList(expression: AbstractExpression): void {
-        for (var idx: number = 0, len = this.expressions.Count; idx < len; ++idx) {
+        for (var idx: number = 0, len = this.expressions.length; idx < len; ++idx) {
             var entry: MultiExpressionEntry = this.expressions[idx];
             if (entry.expression == expression) {
-                this.expressions.Remove(entry);
+                this.expressions.splice(idx, 1);
                 break;
             }
         }

+ 15 - 15
src/MusicalScore/VoiceData/Expressions/multiTempoExpression.ts

@@ -6,23 +6,23 @@ import {OSMDFontStyles} from "../../../Common/Enums/osmdFontStyles";
 import {AbstractTempoExpression} from "./abstractTempoExpression";
 import {ContinuousTempoExpression} from "./ContinuousExpressions/continuousTempoExpression";
 
-export class MultiTempoExpression implements IComparable<MultiTempoExpression>
-{
+export class MultiTempoExpression /*implements IComparable<MultiTempoExpression>*/ {
     constructor(sourceMeasure: SourceMeasure, timestamp: Fraction) {
         this.sourceMeasure = sourceMeasure;
         this.timestamp = timestamp;
     }
+
     private timestamp: Fraction;
     private sourceMeasure: SourceMeasure;
     private instantaniousTempo: InstantaniousTempoExpression;
     private continuousTempo: ContinuousTempoExpression;
-    private expressions: Array<TempoExpressionEntry> = new Array<TempoExpressionEntry>();
+    private expressions: Array<TempoExpressionEntry> = [];
     private combinedExpressionsText: string;
     public get Timestamp(): Fraction {
         return this.timestamp;
     }
     public get AbsoluteTimestamp(): Fraction {
-        return this.sourceMeasure.AbsoluteTimestamp + this.timestamp;
+        return Fraction.plus(this.sourceMeasure.AbsoluteTimestamp, this.timestamp);
     }
     public get SourceMeasureParent(): SourceMeasure {
         return this.sourceMeasure;
@@ -63,17 +63,17 @@ export class MultiTempoExpression implements IComparable<MultiTempoExpression>
             fontStyle = OSMDFontStyles.Italic;
         return fontStyle;
     }
-    public getFirstEntry(graphicalLabel: GraphicalLabel): AbstractGraphicalExpression {
-        var indexOfFirstNotInstDynExpr: number = 0;
-        if (this.expressions.length > 0) {
-            if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof InstantaniousTempoExpression)
-                return new GraphicalInstantaniousTempoExpression(<InstantaniousTempoExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphicalLabel);
-            else if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof ContinuousTempoExpression)
-                return new GraphicalContinuousTempoExpression(<ContinuousTempoExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphicalLabel);
-            else return null;
-        }
-        return null;
-    }
+    //public getFirstEntry(graphicalLabel: GraphicalLabel): AbstractGraphicalExpression {
+    //    var indexOfFirstNotInstDynExpr: number = 0;
+    //    if (this.expressions.length > 0) {
+    //        if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof InstantaniousTempoExpression)
+    //            return new GraphicalInstantaniousTempoExpression(<InstantaniousTempoExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphicalLabel);
+    //        else if (this.expressions[indexOfFirstNotInstDynExpr].expression instanceof ContinuousTempoExpression)
+    //            return new GraphicalContinuousTempoExpression(<ContinuousTempoExpression>(this.expressions[indexOfFirstNotInstDynExpr].expression), graphicalLabel);
+    //        else return null;
+    //    }
+    //    return null;
+    //}
     public addExpression(abstractTempoExpression: AbstractTempoExpression, prefix: string): void {
         if (abstractTempoExpression instanceof InstantaniousTempoExpression) {
             this.instantaniousTempo = <InstantaniousTempoExpression>abstractTempoExpression;

+ 9 - 6
src/MusicalScore/VoiceData/Expressions/unknownExpression.ts

@@ -1,20 +1,23 @@
 import {PlacementEnum, AbstractExpression} from "./abstractExpression";
 import {OSMDTextAlignment} from "../../../Common/Enums/osmdTextAlignment";
-export class UnknownExpression extends AbstractExpression {
-    constructor(label: string, placementEnum: PlacementEnum, staffNumber: number) {
-        this(label, placementEnum, OSMDTextAlignment.LeftBottom, staffNumber);
 
-    }
+export class UnknownExpression extends AbstractExpression {
+    //constructor(label: string, placementEnum: PlacementEnum, staffNumber: number) {
+    //    this(label, placementEnum, OSMDTextAlignment.LeftBottom, staffNumber);
+    //
+    //}
     constructor(label: string, placementEnum: PlacementEnum, textAlignment: OSMDTextAlignment, staffNumber: number) {
+        super();
         this.label = label;
         this.placement = placementEnum;
         this.staffNumber = staffNumber;
-        this.textAlignment = textAlignment;
+        this.textAlignment = textAlignment | OSMDTextAlignment.LeftBottom;
     }
     private label: string;
     private placement: PlacementEnum;
     private textAlignment: OSMDTextAlignment;
     private staffNumber: number;
+
     public get Label(): string {
         return this.label;
     }
@@ -33,4 +36,4 @@ export class UnknownExpression extends AbstractExpression {
     public get TextAlignment(): OSMDTextAlignment {
         return this.textAlignment;
     }
-}
+}

+ 6 - 6
src/MusicalScore/VoiceData/HelperObjects/DynamicsContainer.ts

@@ -3,12 +3,12 @@ import {InstantaniousDynamicExpression} from "../Expressions/instantaniousDynami
 import {MultiExpression} from "../Expressions/multiExpression";
 
 export class DynamicsContainer /*implements IComparable<DynamicsContainer>*/ {
-    constructor(continuousDynamicExpression: ContinuousDynamicExpression, staffNumber: number) {
-        this.ContinuousDynamicExpression = continuousDynamicExpression;
-        this.StaffNumber = staffNumber;
-    }
-    constructor(instantaniousDynamicExpression: InstantaniousDynamicExpression, staffNumber: number) {
-        this.InstantaneousDynamicExpression = instantaniousDynamicExpression;
+    constructor(dynamicExpression: ContinuousDynamicExpression|InstantaniousDynamicExpression, staffNumber: number) {
+        if (dynamicExpression instanceof ContinuousDynamicExpression) {
+            this.ContinuousDynamicExpression = dynamicExpression;
+        } else if (dynamicExpression instanceof InstantaniousDynamicExpression) {
+            this.InstantaneousDynamicExpression = dynamicExpression;
+        }
         this.StaffNumber = staffNumber;
     }
 

+ 9 - 3
src/MusicalScore/VoiceData/Instructions/KeyInstruction.ts

@@ -7,8 +7,9 @@ import {Pitch} from "../../../Common/DataObjects/pitch";
 
 export class KeyInstruction extends AbstractNotationInstruction {
   constructor(first: SourceStaffEntry|KeyInstruction, key?: number, mode?: KeyEnum) {
+    // FIXME Andrea: check this constructor
     if (first === undefined) {
-      super(undefined); // FIXME check
+      super(undefined);
       this.Key = key;
       this.mode = mode;
     }
@@ -20,8 +21,13 @@ export class KeyInstruction extends AbstractNotationInstruction {
     }
     if (first instanceof KeyInstruction) {
       let keyInstruction: KeyInstruction = <KeyInstruction> first;
-      super(undefined); // FIXME check
-      this(keyInstruction.parent, keyInstruction.keyType, keyInstruction.mode);
+      //super(undefined);
+      //this(keyInstruction.parent, keyInstruction.keyType, keyInstruction.mode);
+      if (keyInstruction.parent instanceof SourceStaffEntry) {
+        super(keyInstruction.parent);
+      } else {
+        super(undefined);
+      }
       this.keyType = keyInstruction.keyType;
       this.mode = keyInstruction.mode;
     }

+ 3 - 7
src/MusicalScore/VoiceData/Instructions/RhythmInstruction.ts

@@ -9,13 +9,6 @@ export class RhythmInstruction extends AbstractNotationInstruction {
         this.denominator = denominator;
         this.symbolEnum = rhythmSymbolEnum;
     }
-    constructor(rhythmInstruction: RhythmInstruction) {
-        super(rhythmInstruction.parent);
-        this.rhythm = rhythmInstruction.rhythm;
-        this.numerator = rhythmInstruction.numerator;
-        this.denominator = rhythmInstruction.denominator;
-        this.symbolEnum = rhythmInstruction.symbolEnum;
-    }
     private numerator: number;
     private denominator: number;
     private rhythm: Fraction;
@@ -32,6 +25,9 @@ export class RhythmInstruction extends AbstractNotationInstruction {
     public set SymbolEnum(value: RhythmSymbolEnum) {
         this.symbolEnum = value;
     }
+    public clone() {
+        return new RhythmInstruction(this.rhythm.clone(), this.numerator, this.denominator, this.symbolEnum);
+    }
     public OperatorEquals(rhythm2: RhythmInstruction): boolean {
         let rhythm1: RhythmInstruction = this;
         if (rhythm1 === rhythm2) {

+ 6 - 6
src/MusicalScore/VoiceData/SourceMeasure.ts

@@ -167,7 +167,7 @@ export class SourceMeasure {
   public findOrCreateVoiceEntry(sse: SourceStaffEntry, voice: Voice): { createdVoiceEntry: boolean, voiceEntry: VoiceEntry } {
     let ve: VoiceEntry = undefined;
     let createdNewVoiceEntry: boolean = false;
-    for (let voiceEntry: VoiceEntry of sse.VoiceEntries) {
+    for (let voiceEntry of sse.VoiceEntries) {
       if (voiceEntry.ParentVoice === voice) {
         ve = voiceEntry;
         break;
@@ -178,7 +178,7 @@ export class SourceMeasure {
       sse.VoiceEntries.push(ve);
       createdNewVoiceEntry = true;
     }
-    return { createdVoiceEntry: createdVoiceEntry, voiceEntry: ve };
+    return { createdVoiceEntry: createdNewVoiceEntry, voiceEntry: ve };
   }
   public getPreviousSourceStaffEntryFromIndex(
     verticalIndex: number, horizontalIndex: number
@@ -233,8 +233,8 @@ export class SourceMeasure {
           for (let m: number = verticalContainerIndex - 1; m >= 0; m--) {
             let previousStaffEntry: SourceStaffEntry = this.verticalSourceStaffEntryContainers[m][inSourceMeasureInstrumentIndex + j];
             if (previousStaffEntry !== undefined && previousStaffEntry.hasTie()) {
-              if (instrumentDuration < previousStaffEntry.Timestamp + previousStaffEntry.calculateMaxNoteLength()) {
-                instrumentDuration = previousStaffEntry.Timestamp + previousStaffEntry.calculateMaxNoteLength();
+              if (instrumentDuration.lt(Fraction.plus(previousStaffEntry.Timestamp, previousStaffEntry.calculateMaxNoteLength()))) {
+                instrumentDuration = Fraction.plus(previousStaffEntry.Timestamp, previousStaffEntry.calculateMaxNoteLength());
                 break;
               }
             }
@@ -259,8 +259,8 @@ export class SourceMeasure {
       for (let j: number = 0; j < musicSheet.Instruments[i].Staves.length; j++) {
         let lastStaffEntry: SourceStaffEntry = this.getLastSourceStaffEntryForInstrument(inSourceMeasureInstrumentIndex + j);
         if (lastStaffEntry !== undefined && lastStaffEntry.Timestamp !== undefined) {
-          if (instrumentDuration < lastStaffEntry.Timestamp + lastStaffEntry.calculateMaxNoteLength()) {
-            instrumentDuration = new Fraction(lastStaffEntry.Timestamp + lastStaffEntry.calculateMaxNoteLength());
+          if (instrumentDuration.lt(Fraction.plus(lastStaffEntry.Timestamp, lastStaffEntry.calculateMaxNoteLength()))) {
+            instrumentDuration = Fraction.plus(lastStaffEntry.Timestamp, lastStaffEntry.calculateMaxNoteLength());
           }
         }
       }

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

@@ -34,7 +34,7 @@ export class SourceStaffEntry {
   }
   public get AbsoluteTimestamp(): Fraction {
     if (this.VerticalContainerParent !== undefined) {
-      return this.VerticalContainerParent.ParentMeasure.AbsoluteTimestamp + this.VerticalContainerParent.Timestamp;
+      return Fraction.plus(this.VerticalContainerParent.ParentMeasure.AbsoluteTimestamp, this.VerticalContainerParent.Timestamp);
     }
     return undefined;
   }