Browse Source

Pull changes

Andrea Condoluci 9 năm trước cách đây
mục cha
commit
aa97180c48

+ 4 - 4
src/Common/logging.ts

@@ -4,10 +4,10 @@
 
 
 export class logging {
-    public static debug(...arguments: any[]) {
-        console.log("[OSMD] DEBUG: ", arguments.join(" "));
+    public static debug(...args: any[]) {
+        console.log("[OSMD] DEBUG: ", args.join(" "));
     }
-    public static log(...arguments: any[]) {
-        console.log("[OSMD] ", arguments.join(" "));
+    public static log(...args: any[]) {
+        console.log("[OSMD] ", args.join(" "));
     }
 }

+ 2 - 21
src/MusicalScore/Instrument.ts

@@ -6,16 +6,10 @@ import { Staff } from "./VoiceData/Staff";
 import { SubInstrument } from "./SubInstrument";
 import { MidiInstrument } from "./VoiceData/Instructions/ClefInstruction";
 
-// FIXME
-type IPhonicScoreInterface = any;
-type InstrumentParameters = any;
-type InstrumentParameterChangedDelegate = any;
 
-
-export class Instrument extends InstrumentalGroup /*implements ISettableInstrument, IInstrument*/ {
-    constructor(id: number, idString: string, phonicScoreInterface: IPhonicScoreInterface, musicSheet: MusicSheet, parent: InstrumentalGroup) {
+export class Instrument extends InstrumentalGroup {
+    constructor(id: number, idString: string, musicSheet: MusicSheet, parent: InstrumentalGroup) {
         super(undefined, musicSheet, parent);
-        this.phonicScoreInterface = phonicScoreInterface;
         this.id = id;
         this.idString = idString;
         this.nameLabel = new Label(idString);
@@ -23,13 +17,10 @@ export class Instrument extends InstrumentalGroup /*implements ISettableInstrume
 
     public Transpose: number = 0;
     public Highlight: boolean;
-    public InstrumentParameterChanged: InstrumentParameterChangedDelegate;
 
-    private phonicScoreInterface: IPhonicScoreInterface;
     private voices: Voice[] = [];
     private staves: Staff[] = [];
     private nameLabel: Label;
-    // private range: ToneRange;
     private idString: string;
     private id: number;
     private hasLyrics: boolean = false;
@@ -71,9 +62,6 @@ export class Instrument extends InstrumentalGroup /*implements ISettableInstrume
     public set Name(value: string) {
         this.nameLabel.Text = value;
     }
-    public set PhonicScoreInterface(value: IPhonicScoreInterface) {
-        this.phonicScoreInterface = value;
-    }
     public get IdString(): string {
         return this.idString;
     }
@@ -250,11 +238,4 @@ export class Instrument extends InstrumentalGroup /*implements ISettableInstrume
             this.staves.push(new Staff(this, i + 1));
         }
     }
-    public SetInstrumentParameter(parameter: InstrumentParameters, value: Object): void {
-        this.phonicScoreInterface.RequestInstrumentParameter(this.Id, parameter, value);
-    }
-
-    public Dispose(): void {
-        this.InstrumentParameterChanged = undefined;
-    }
 }

+ 121 - 0
src/MusicalScore/VoiceData/Expressions/ContinuousExpressions/continuousDynamicExpression.ts

@@ -0,0 +1,121 @@
+import {PlacementEnum, AbstractExpression} from "../abstractExpression";
+import {MultiExpression} from "../multiExpression";
+import {Fraction} from "../../../../Common/DataObjects/fraction";
+export class ContinuousDynamicExpression extends AbstractExpression {
+    constructor(placement: PlacementEnum, staffNumber: number, label: string) {
+        this.label = label;
+        this.placement = placement;
+        this.staffNumber = staffNumber;
+        this.startVolume = -1;
+        this.endVolume = -1;
+        this.setType();
+    }
+    constructor(dynamicType: ContDynamicEnum, placement: PlacementEnum, staffNumber: number) {
+        this.dynamicType = dynamicType;
+        this.label = null;
+        this.placement = placement;
+        this.staffNumber = staffNumber;
+        this.startVolume = -1;
+        this.endVolume = -1;
+    }
+    private static listContinuousDynamicIncreasing: Array<string> = __init(new Array<string>(), { "crescendo","cresc","cresc.","cres." });
+    private static listContinuousDynamicDecreasing: Array<string> = __init(new Array<string>(), { "decrescendo","decresc","decr.","diminuendo","dim.","dim" });
+    private static listContinuousDynamicGeneral: Array<string> = __init(new Array<string>(), { "subito","al niente","piu","meno" });
+    private dynamicType: ContDynamicEnum;
+    private startMultiExpression: MultiExpression;
+    private endMultiExpression: MultiExpression;
+    private startVolume: number;
+    private endVolume: number;
+    private placement: PlacementEnum;
+    private staffNumber: number;
+    private label: string;
+    public get DynamicType(): ContDynamicEnum {
+        return this.dynamicType;
+    }
+    public set DynamicType(value: ContDynamicEnum) {
+        this.dynamicType = value;
+    }
+    public get StartMultiExpression(): MultiExpression {
+        return this.startMultiExpression;
+    }
+    public set StartMultiExpression(value: MultiExpression) {
+        this.startMultiExpression = value;
+    }
+    public get EndMultiExpression(): MultiExpression {
+        return this.endMultiExpression;
+    }
+    public set EndMultiExpression(value: MultiExpression) {
+        this.endMultiExpression = value;
+    }
+    public get Placement(): PlacementEnum {
+        return this.placement;
+    }
+    public set Placement(value: PlacementEnum) {
+        this.placement = value;
+    }
+    public get StartVolume(): number {
+        return this.startVolume;
+    }
+    public set StartVolume(value: number) {
+        this.startVolume = value;
+    }
+    public get EndVolume(): number {
+        return this.endVolume;
+    }
+    public set EndVolume(value: number) {
+        this.endVolume = value;
+    }
+    public get StaffNumber(): number {
+        return this.staffNumber;
+    }
+    public set StaffNumber(value: number) {
+        this.staffNumber = value;
+    }
+    public get Label(): string {
+        return this.label;
+    }
+    public set Label(value: string) {
+        this.label = value;
+    }
+    public static isInputStringContinuousDynamic(inputString: string): boolean {
+        if (inputString == null)
+            return false;
+        if (isStringInStringList(ContinuousDynamicExpression.listContinuousDynamicIncreasing, inputString))
+            return true;
+        if (isStringInStringList(ContinuousDynamicExpression.listContinuousDynamicDecreasing, inputString))
+            return true;
+        return false;
+    }
+    public getInterpolatedDynamic(currentAbsoluteTimestamp: Fraction): number {
+        var continuousAbsoluteStartTimestamp: Fraction = this.StartMultiExpression.AbsoluteTimestamp;
+        var continuousAbsoluteEndTimestamp: Fraction;
+        if (this.EndMultiExpression != null)
+            continuousAbsoluteEndTimestamp = this.EndMultiExpression.AbsoluteTimestamp;
+        else {
+            continuousAbsoluteEndTimestamp = 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 interpolatedVolume: number = Math.Max(0.0f, Math.Min(99.9f, this.startVolume + (this.endVolume - this.startVolume) * interpolationRatio));
+        return <number>interpolatedVolume;
+    }
+    public isWedge(): boolean {
+        if (this.label != null)
+            return false;
+        return true;
+    }
+    private setType(): void {
+        if (isStringInStringList(ContinuousDynamicExpression.listContinuousDynamicIncreasing, this.label))
+            this.dynamicType = ContDynamicEnum.crescendo;
+        else if (isStringInStringList(ContinuousDynamicExpression.listContinuousDynamicDecreasing, this.label))
+            this.dynamicType = ContDynamicEnum.diminuendo;
+    }
+}
+export enum ContDynamicEnum {
+    crescendo = 0,
+
+    diminuendo = 1
+}

+ 102 - 0
src/MusicalScore/VoiceData/Expressions/ContinuousExpressions/continuousTempoExpression.ts

@@ -0,0 +1,102 @@
+import {Fraction} from "../../../../Common/DataObjects/fraction";
+import {PlacementEnum} from "../abstractExpression";
+import {MultiTempoExpression} from "../multiTempoExpression";
+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;
+        this.setTempoType();
+    }
+    private absoluteEndTimestamp: Fraction;
+    private tempoType: ContinuousTempoType;
+    private startTempo: number;
+    private endTempo: number;
+    private static listContinuousTempoFaster: Array<string> = __init(new Array<string>(), { "accelerando","piu mosso","poco piu","stretto" });
+    private static listContinuousTempoSlower: Array<string> = __init(new Array<string>(), { "poco meno","meno mosso","piu lento","calando","allargando","rallentando","ritardando","ritenuto","ritard.","ritard","rit.","rit","riten.","riten" });
+    public get TempoType(): ContinuousTempoType {
+        return this.tempoType;
+    }
+    public set TempoType(value: ContinuousTempoType) {
+        this.tempoType = value;
+    }
+    public get StartTempo(): number {
+        return this.startTempo;
+    }
+    public set StartTempo(value: number) {
+        this.startTempo = value;
+    }
+    public get EndTempo(): number {
+        return this.endTempo;
+    }
+    public set EndTempo(value: number) {
+        this.endTempo = value;
+    }
+    public get AbsoluteEndTimestamp(): Fraction {
+        return this.absoluteEndTimestamp;
+    }
+    public set AbsoluteEndTimestamp(value: Fraction) {
+        this.absoluteEndTimestamp = value;
+    }
+    public static isInputStringContinuousTempo(inputString: string): boolean {
+        if (inputString == null)
+            return false;
+        if (isStringInStringList(ContinuousTempoExpression.listContinuousTempoFaster, inputString))
+            return true;
+        if (isStringInStringList(ContinuousTempoExpression.listContinuousTempoSlower, inputString))
+            return true;
+        return false;
+    }
+    private setTempoType(): void {
+        if (isStringInStringList(ContinuousTempoExpression.listContinuousTempoFaster, label))
+            this.tempoType = ContinuousTempoType.accelerando;
+        else if (isStringInStringList(ContinuousTempoExpression.listContinuousTempoSlower, label))
+            this.tempoType = ContinuousTempoType.ritardando;
+    }
+    public get AbsoluteTimestamp(): Fraction {
+        return (ParentMultiTempoExpression.AbsoluteTimestamp);
+    }
+    public getAbsoluteFloatTimestamp(): number {
+        return (ParentMultiTempoExpression.AbsoluteTimestamp).RealValue;
+    }
+    public getInterpolatedTempo(currentAbsoluteTimestamp: Fraction): number {
+        var continuousAbsoluteStartTimestamp: Fraction = parentMultiTempoExpression.SourceMeasureParent.AbsoluteTimestamp + parentMultiTempoExpression.Timestamp;
+        if (currentAbsoluteTimestamp < continuousAbsoluteStartTimestamp)
+            return -1;
+        if (currentAbsoluteTimestamp > this.absoluteEndTimestamp)
+            return -2;
+        var interpolationRatio: number = (currentAbsoluteTimestamp - continuousAbsoluteStartTimestamp).RealValue / (this.absoluteEndTimestamp - continuousAbsoluteStartTimestamp).RealValue;
+        var interpolatedTempo: number = Math.Max(0.0f, Math.Min(250.0f, this.startTempo + (this.endTempo - this.startTempo) * interpolationRatio));
+        return <number>interpolatedTempo;
+    }
+    public static isIncreasingTempo(tempoType: ContinuousTempoType): boolean {
+        if (tempoType <= ContinuousTempoType.piuMosso)
+            return true;
+        else return false;
+    }
+    public static isDecreasingTempo(tempoType: ContinuousTempoType): boolean {
+        if ((tempoType >= ContinuousTempoType.allargando) && (tempoType <= ContinuousTempoType.ritenuto))
+            return true;
+        else return false;
+    }
+}
+export enum ContinuousTempoType {
+    accelerando = 0,
+    stretto = 1,
+    stringendo = 2,
+    mosso = 3,
+    piuMosso = 4,
+    allargando = 5,
+    calando = 6,
+    menoMosso = 7,
+    rallentando = 8,
+    ritardando = 9,
+    ritard = 10,
+    rit = 11,
+    ritenuto = 12,
+    rubato = 13,
+    precipitando = 14
+}

+ 53 - 0
src/MusicalScore/VoiceData/Expressions/ContinuousExpressions/octaveShift.ts

@@ -0,0 +1,53 @@
+import {MultiExpression} from "../multiExpression";
+
+export class OctaveShift {
+    constructor(type: string, octave: number) {
+        this.setOctaveShiftValue(type, octave);
+    }
+    private octaveValue: OctaveEnum;
+    private staffNumber: number;
+    private startMultiExpression: MultiExpression;
+    private endMultiExpression: MultiExpression;
+    public get Type(): OctaveEnum {
+        return this.octaveValue;
+    }
+    public set Type(value: OctaveEnum) {
+        this.octaveValue = value;
+    }
+    public get StaffNumber(): number {
+        return this.staffNumber;
+    }
+    public set StaffNumber(value: number) {
+        this.staffNumber = value;
+    }
+    public get ParentStartMultiExpression(): MultiExpression {
+        return this.startMultiExpression;
+    }
+    public set ParentStartMultiExpression(value: MultiExpression) {
+        this.startMultiExpression = value;
+    }
+    public get ParentEndMultiExpression(): MultiExpression {
+        return this.endMultiExpression;
+    }
+    public set ParentEndMultiExpression(value: MultiExpression) {
+        this.endMultiExpression = value;
+    }
+    private setOctaveShiftValue(type: string, octave: number): void {
+        if (octave == 1 && type == "down")
+            this.octaveValue = OctaveEnum.VA8;
+        else if (octave == 1 && type == "up")
+            this.octaveValue = OctaveEnum.VB8;
+        else if (octave == 2 && type == "down")
+            this.octaveValue = OctaveEnum.MA15;
+        else if (octave == 2 && type == "up")
+            this.octaveValue = OctaveEnum.MB15;
+        else this.octaveValue = OctaveEnum.NONE;
+    }
+}
+export enum OctaveEnum {
+    VA8,
+    VB8,
+    MA15,
+    MB15,
+    NONE
+}

+ 19 - 0
src/MusicalScore/VoiceData/Expressions/abstractExpression.ts

@@ -0,0 +1,19 @@
+export class AbstractExpression {
+    constructor() {
+
+    }
+    protected static isStringInStringList(stringList: Array<string>, inputString: string): boolean {
+        for (var idx: number = 0, len = stringList.length; idx < len; ++idx) {
+            var s: string = stringList[idx];
+            if (inputString.toLowerCase() === s.toLowerCase().trim())
+                return true;
+        }
+        return false;
+    }
+}
+
+export enum PlacementEnum {
+    Above = 0,
+    Below = 1,
+    NotYetDefined = 2
+}

+ 42 - 0
src/MusicalScore/VoiceData/Expressions/abstractTempoExpression.ts

@@ -0,0 +1,42 @@
+import {PlacementEnum} from "./abstractExpression";
+import {MultiTempoExpression} from "./multiTempoExpression";
+export class AbstractTempoExpression {
+    protected label: string;
+    protected placement: PlacementEnum;
+    protected staffNumber: number;
+    protected parentMultiTempoExpression: MultiTempoExpression;
+    public get Label(): string {
+        return this.label;
+    }
+    public set Label(value: string) {
+        this.label = value;
+    }
+    public get Placement(): PlacementEnum {
+        return this.placement;
+    }
+    public set Placement(value: PlacementEnum) {
+        this.placement = value;
+    }
+    public get StaffNumber(): number {
+        return this.staffNumber;
+    }
+    public set StaffNumber(value: number) {
+        this.staffNumber = value;
+    }
+    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()))
+                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;
+    }
+}

+ 8 - 0
src/MusicalScore/VoiceData/Expressions/dynamicExpressionSymbolEnum.ts

@@ -0,0 +1,8 @@
+export enum DynamicExpressionSymbolEnum {
+    p = 0,
+    f = 1,
+    s = 2,
+    z = 3,
+    m = 4,
+    r = 5
+}

+ 203 - 0
src/MusicalScore/VoiceData/Expressions/instantaniousDynamicExpression.ts

@@ -0,0 +1,203 @@
+import {PlacementEnum, AbstractExpression} from "./abstractExpression";
+import {MultiExpression} from "./multiExpression";
+import {DynamicExpressionSymbolEnum} from "./dynamicExpressionSymbolEnum";
+
+export class InstantaniousDynamicExpression extends AbstractExpression {
+    constructor(dynamicExpression: string, soundDynamics: number, placement: PlacementEnum, staffNumber: number) {
+        this.dynamicEnum = <DynamicEnum>Enum.Parse(/*typeof*/DynamicEnum, dynamicExpression.ToLower());
+        this.soundDynamic = soundDynamics;
+        this.placement = placement;
+        this.staffNumber = staffNumber;
+    }
+    public static dynamicToRelativeVolumeDict: SortedDictionary<DynamicEnum, number> = __init(new SortedDictionary<DynamicEnum, number>(), { { DynamicEnum.ffffff, 127.0f / 127.0f },
+        { DynamicEnum.fffff, 126.0f / 127.0f },
+        { DynamicEnum.ffff, 125.0f / 127.0f },
+        { DynamicEnum.fff, 124.0f / 127.0f },
+        { DynamicEnum.ff, 108.0f / 127.0f },
+        { DynamicEnum.f, 92.0f / 127.0f },
+        { DynamicEnum.mf, 76.0f / 127.0f },
+        { DynamicEnum.mp, 60.0f / 127.0f },
+        { DynamicEnum.p, 44.0f / 127.0f },
+        { DynamicEnum.pp, 28.0f / 127.0f },
+        { DynamicEnum.ppp, 12.0f / 127.0f },
+        { DynamicEnum.pppp, 10.0f / 127.0f },
+        { DynamicEnum.ppppp, 8.0f / 127.0f },
+        { DynamicEnum.pppppp, 6.0f / 127.0f },
+        { DynamicEnum.sf, 0.5f },
+        { DynamicEnum.sfp, 0.5f },
+        { DynamicEnum.sfpp, 0.5f },
+        { DynamicEnum.fp, 0.5f },
+        { DynamicEnum.rf, 0.5f },
+        { DynamicEnum.rfz, 0.5f },
+        { DynamicEnum.sfz, 0.5f },
+        { DynamicEnum.sffz, 0.5f },
+        { DynamicEnum.fz, 0.5f } });
+private static weight: number;
+static private  listInstantaniousDynamics: Array < string >  =  __init(new Array<string>(), {
+    "pppppp","ppppp","pppp","ppp","pp","p",
+    "ffffff","fffff","ffff","fff","ff","f",
+    "mf","mp","sf","sp","spp","fp","rf","rfz","sfz","sffz","fz" });
+private multiExpression: MultiExpression;
+private dynamicEnum: DynamicEnum;
+private soundDynamic: number;
+private placement: PlacementEnum;
+private staffNumber: number;
+private length: number;
+public get ParentMultiExpression(): MultiExpression
+{
+    return this.multiExpression;
+}
+public set ParentMultiExpression(value: MultiExpression)
+{
+    this.multiExpression = value;
+}
+public get DynEnum(): DynamicEnum
+{
+    return this.dynamicEnum;
+}
+public set DynEnum(value: DynamicEnum)
+{
+    this.dynamicEnum = value;
+}
+public get SoundDynamic(): number
+{
+    return this.soundDynamic;
+}
+public set SoundDynamic(value: number)
+{
+    this.soundDynamic = value;
+}
+public get Placement(): PlacementEnum
+{
+    return this.placement;
+}
+public set Placement(value: PlacementEnum)
+{
+    this.placement = value;
+}
+public get StaffNumber(): number
+{
+    return this.staffNumber;
+}
+public set StaffNumber(value: number)
+{
+    this.staffNumber = value;
+}
+public get Length(): number
+{
+    if (Math.Abs(this.length - 0.0f) < 0.0001f)
+    this.length = this.calculateLength();
+    return this.length;
+}
+public get MidiVolume(): number
+{
+    return InstantaniousDynamicExpression.dynamicToRelativeVolumeDict[this.dynamicEnum] * 127f;
+}
+public static isInputStringInstantaniousDynamic(inputString:string): boolean
+{
+    if (inputString == null)
+        return false;
+    if (isStringInStringList(InstantaniousDynamicExpression.listInstantaniousDynamics, inputString))
+        return true;
+    return false;
+}
+public getInstantaniousDynamicSymbol(expressionSymbolEnum:DynamicExpressionSymbolEnum): FontInfo.MusicFontSymbol
+{
+    switch (expressionSymbolEnum) {
+        case DynamicExpressionSymbolEnum.p:
+            return FontInfo.MusicFontSymbol.P;
+        case DynamicExpressionSymbolEnum.f:
+            return FontInfo.MusicFontSymbol.F;
+        case DynamicExpressionSymbolEnum.s:
+            return FontInfo.MusicFontSymbol.S;
+        case DynamicExpressionSymbolEnum.z:
+            return FontInfo.MusicFontSymbol.Z;
+        case DynamicExpressionSymbolEnum.m:
+            return FontInfo.MusicFontSymbol.M;
+        case DynamicExpressionSymbolEnum.r:
+            return FontInfo.MusicFontSymbol.R;
+        default:
+            throw new ArgumentOutOfRangeException("expressionSymbolEnum");
+    }
+}
+public getDynamicExpressionSymbol(c:string): DynamicExpressionSymbolEnum
+{
+    switch (c) {
+        case 'p':
+            return DynamicExpressionSymbolEnum.p;
+        case 'f':
+            return DynamicExpressionSymbolEnum.f;
+        case 's':
+            return DynamicExpressionSymbolEnum.s;
+        case 'z':
+            return DynamicExpressionSymbolEnum.z;
+        case 'm':
+            return DynamicExpressionSymbolEnum.m;
+        case 'r':
+            return DynamicExpressionSymbolEnum.r;
+        default:
+            throw new InvalidEnumArgumentException("unknown DynamicExpressionSymbolEnum: " + c);
+    }
+}
+private calculateLength(): number
+{
+    var length: number = 0.0f;
+    var dynamic: string = this.dynamicEnum.ToString();
+    for (var idx: number = 0, len = dynamic.length; idx < len; ++idx) {
+        var c: string = dynamic[idx];
+        var dynamicExpressionSymbol: DynamicExpressionSymbolEnum = this.getDynamicExpressionSymbol(c);
+        var symbol: FontInfo.MusicFontSymbol = this.getInstantaniousDynamicSymbol(dynamicExpressionSymbol);
+        length += FontInfo.Info.getBoundingBox(symbol).Width;
+    }
+    return length;
+} 
+                }
+export enum DynamicEnum {
+    pppppp = 0,
+
+    ppppp = 1,
+
+    pppp = 2,
+
+    ppp = 3,
+
+    pp = 4,
+
+    p = 5,
+
+    mp = 6,
+
+    mf = 7,
+
+    f = 8,
+
+    ff = 9,
+
+    fff = 10,
+
+    ffff = 11,
+
+    fffff = 12,
+
+    ffffff = 13,
+
+    sf = 14,
+
+    sfp = 15,
+
+    sfpp = 16,
+
+    fp = 17,
+
+    rf = 18,
+
+    rfz = 19,
+
+    sfz = 20,
+
+    sffz = 21,
+
+    fz = 22,
+
+    other = 23
+}

+ 425 - 0
src/MusicalScore/VoiceData/Expressions/instantaniousTempoExpression.ts

@@ -0,0 +1,425 @@
+import {AbstractTempoExpression} from "./abstractTempoExpression";
+import {PlacementEnum} from "./abstractExpression";
+import {ArgumentOutOfRangeException} from "../../Exceptions";
+import {Fraction} from "../../../Common/DataObjects/fraction";
+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;
+        this.setTempoAndTempoType(soundTempo);
+    }
+    private tempoEnum: TempoEnum;
+    private tempoInBpm: number;
+    private findTempoEnum(inputString: string, pre: string, post: string): TempoEnum {
+        var result: TempoEnum = this.splitStringAfterInstructionWord(inputString, InstantaniousTempoExpression.listInstantaniousTempoLarghissimo, pre,
+            post);
+        if (result != TempoEnum.none)
+            return result;
+        result = this.splitStringAfterInstructionWord(inputString, InstantaniousTempoExpression.listInstantaniousTempoGrave, pre,
+            post);
+        if (result != TempoEnum.none)
+            return result;
+        return TempoEnum.none;
+    }
+    private splitStringAfterInstructionWord(inputString: string, instruction: KeyValuePair<Array<string>, TempoEnum>, pre: string, post: string): TempoEnum {
+        pre = null;
+        post = null;
+        for (var idx: number = 0, len = instruction.Key.Count; idx < len; ++idx) {
+            var instructionWord: string = instruction.Key[idx];
+            var separators: string[] = " " + instructionWord, instructionWord + " ","," + instructionWord, instructionWord + ",";
+            var splits: string[] = inputString.Split(separators, 2, StringSplitOptions.None);
+            if (splits.length > 1) {
+                pre = splits[0];
+                post = splits[1];
+                return instruction.Value;
+            }
+        }
+        return TempoEnum.none;
+    }
+    static private listInstantaniousTempoLarghissimo: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Larghissimo","Sehr breit","very, very slow" }), TempoEnum.larghissimo);
+    static private listInstantaniousTempoGrave: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Grave","Schwer","slow and solemn" }), TempoEnum.grave);
+    static private listInstantaniousTempoLento: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Lento","Lent","Langsam","slowly" }), TempoEnum.lento);
+    static private listInstantaniousTempoLargo: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Largo","Breit","broadly" }), TempoEnum.largo);
+    static private listInstantaniousTempoLarghetto: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Larghetto","Etwas breit","rather broadly" }), TempoEnum.larghetto);
+    static private listInstantaniousTempoAdagio: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Adagio","Langsam","Ruhig","slow and stately" }), TempoEnum.adagio);
+    static private listInstantaniousTempoAdagietto: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Adagietto","Ziemlich ruhig","Ziemlich langsam","rather slow" }), TempoEnum.adagietto);
+    static private listInstantaniousTempoAndanteModerato: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Andante moderato" }), TempoEnum.andanteModerato);
+    static private listInstantaniousTempoAndante: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Andante","Gehend","Schreitend","at a walking pace" }), TempoEnum.andante);
+    static private listInstantaniousTempoAndantino: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Andantino" }), TempoEnum.andantino);
+    static private listInstantaniousTempoModerato: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Moderato","M��ig","Mod�r�","moderately" }), TempoEnum.moderato);
+    static private listInstantaniousTempoAllegretto: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Allegretto","fast" }), TempoEnum.allegretto);
+    static private listInstantaniousTempoAllegroModerato: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Allegro moderato" }), TempoEnum.allegroModerato);
+    static private listInstantaniousTempoAllegro: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Allegro","Rapide","Vite","Rasch","Schnell","Fr�hlich" }), TempoEnum.allegro);
+    static private listInstantaniousTempoVivace: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Vivace","Lebhaft","Lebendig","lively and fast" }), TempoEnum.vivace);
+    static private listInstantaniousTempoVivacissimo: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Vivacissimo","Sehr lebhaft","Sehr lebendig" }), TempoEnum.vivacissimo);
+    static private listInstantaniousTempoAllegrissimo: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Allegrissimo","very fast" }), TempoEnum.allegrissimo);
+    static private listInstantaniousTempoPresto: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Presto","Sehr schnell","Geschwind" }), TempoEnum.presto);
+    static private listInstantaniousTempoPrestissimo: KeyValuePair<Array<string>, TempoEnum> = new KeyValuePair<Array<string>, TempoEnum>(__init(new Array<string>(), { "Prestissimo","�u�erst schnell" }), TempoEnum.prestissimo);
+    static private listInstantaniousTempoChangesGeneral: Array<string> = __init(new Array<string>(), {
+        "tempo primo",
+        "a tempo",
+        "tempo i",
+        "rubato",
+        "doppio movimento" });
+    static private listInstantaniousTempoAddons: Array<string> = __init(new Array<string>(), {
+        "assai",
+        "amoroso",
+        "cantabile",
+        "con brio",
+        "con dolore",
+        "con espressione",
+        "con fuoco",
+        "con moto",
+        "con spirito",
+        "spiritoso",
+        "espressivo",
+        "giocoso",
+        "giusto",
+        "grazioso",
+        "lesto",
+        "lugubre",
+        "maestoso",
+        "ma non troppo",
+        "marcato",
+        "molto",
+        "morendo",
+        "mosso",
+        "non tanto",
+        "piu",
+        "un poco",
+        "poco",
+        "quasi",
+        "risoluto",
+        "scherzando",
+        "sostenuto",
+        "teneramente",
+        "tempo giusto",
+        "tranquillo",
+        "sehr",
+        "lieblich",
+        "liebevoll",
+        "mit Leidenschaft",
+        "mit Liebe",
+        "amour�s",
+        "gesanglich",
+        "mit Schwung",
+        "mit Feuer",
+        "mit Schmerz",
+        "mit Ausdruck",
+        "mit Bewegung",
+        "geistvoll",
+        "ausdrucksvoll",
+        "freudig",
+        "verspielt",
+        "angemessen",
+        "grazi�s",
+        "mit Grazie",
+        "flink",
+        "beh�nde",
+        "traurig",
+        "klagend",
+        "majest�tisch",
+        "aber nicht zu sehr",
+        "markant",
+        "gem��igt",
+        "viel",
+        "sehr",
+        "ersterbend",
+        "bewegt",
+        "nicht zu sehr",
+        "mehr",
+        "ein wenig",
+        "gleichsam",
+        "entschlossen",
+        "zupackend",
+        "heiter",
+        "nachdr�cklich",
+        "getragen",
+        "gewichtig",
+        "zart",
+        "z�rtlich",
+        "im angemessenen Zeitma�",
+        "ruhig",
+        "ein wenig",
+        "alla marcia",
+        "ad libitum",
+        "alla breve" });
+    public get Label(): string {
+        return label;
+    }
+    public set Label(value: string) {
+        label = value;
+    }
+    public get Placement(): PlacementEnum {
+        return placement;
+    }
+    public set Placement(value: PlacementEnum) {
+        placement = value;
+    }
+    public get StaffNumber(): number {
+        return staffNumber;
+    }
+    public set StaffNumber(value: number) {
+        staffNumber = value;
+    }
+    public get Enum(): TempoEnum {
+        return this.tempoEnum;
+    }
+    public get TempoInBpm(): number {
+        return this.tempoInBpm;
+    }
+    public set TempoInBpm(value: number) {
+        this.tempoInBpm = value;
+    }
+    public get ParentMultiTempoExpression(): MultiTempoExpression {
+        return parentMultiTempoExpression;
+    }
+    public getAbsoluteTimestamp(): Fraction {
+        return (this.ParentMultiTempoExpression.SourceMeasureParent.AbsoluteTimestamp + this.ParentMultiTempoExpression.Timestamp);
+    }
+    public getAbsoluteFloatTimestamp(): number {
+        return (this.ParentMultiTempoExpression.SourceMeasureParent.AbsoluteTimestamp + this.ParentMultiTempoExpression.Timestamp).RealValue;
+    }
+    public static getDefaultValueForTempoType(tempoEnum: TempoEnum): number {
+        switch (tempoEnum) {
+            case TempoEnum.larghissimo:
+                return 20;
+            case TempoEnum.grave:
+                return 30;
+            case TempoEnum.lento:
+                return 48;
+            case TempoEnum.largo:
+                return 52;
+            case TempoEnum.larghetto:
+                return 63;
+            case TempoEnum.adagio:
+                return 70;
+            case TempoEnum.adagietto:
+                return 75;
+            case TempoEnum.andanteModerato:
+                return 88;
+            case TempoEnum.andante:
+                return 92;
+            case TempoEnum.andantino:
+                return 96;
+            case TempoEnum.moderato:
+                return 106;
+            case TempoEnum.allegretto:
+                return 112;
+            case TempoEnum.allegroModerato:
+                return 118;
+            case TempoEnum.allegro:
+                return 130;
+            case TempoEnum.vivace:
+                return 140;
+            case TempoEnum.vivacissimo:
+                return 155;
+            case TempoEnum.allegrissimo:
+                return 170;
+            case TempoEnum.presto:
+                return 184;
+            case TempoEnum.prestissimo:
+                return 200;
+            default:
+                throw new ArgumentOutOfRangeException("tempoEnum");
+        }
+    }
+    public static isInputStringInstantaniousTempo(inputString: string): boolean {
+        if (inputString == null)
+            return false;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLarghissimo.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoGrave.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLento.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLargo.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLarghetto.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAdagio.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAdagietto.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAndanteModerato.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAndante.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAndantino.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoModerato.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegretto.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegroModerato.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegro.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoVivace.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoVivacissimo.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegrissimo.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoPresto.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoPrestissimo.Key, inputString))
+            return true;
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoChangesGeneral, inputString))
+            return true;
+        return false;
+    }
+    private setTempoAndTempoType(soundTempo: number): void {
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLarghissimo.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.larghissimo);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.larghissimo;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoGrave.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.grave);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.grave;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLento.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.lento);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.lento;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLargo.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.largo);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.largo;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoLarghetto.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.larghetto);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.larghetto;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAdagio.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.adagio);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.adagio;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAdagietto.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.adagietto);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.adagietto;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAndanteModerato.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.andanteModerato);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.andanteModerato;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAndante.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.andante);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.andante;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAndantino.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.andantino);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.andantino;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoModerato.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.moderato);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.moderato;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegretto.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.allegretto);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.allegretto;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegroModerato.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.allegroModerato);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.allegroModerato;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegro.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.allegro);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.allegro;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoVivace.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.vivace);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.vivace;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoVivacissimo.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.vivacissimo);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.vivacissimo;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAllegrissimo.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.allegrissimo);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.allegrissimo;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoPresto.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.presto);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.presto;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoPrestissimo.Key, label)) {
+            if (soundTempo == 0)
+                soundTempo = InstantaniousTempoExpression.getDefaultValueForTempoType(TempoEnum.prestissimo);
+            this.tempoInBpm = soundTempo;
+            this.tempoEnum = TempoEnum.prestissimo;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoAddons, label)) {
+            this.tempoInBpm = 0;
+            this.tempoEnum = TempoEnum.addon;
+        }
+        if (isStringInStringList(InstantaniousTempoExpression.listInstantaniousTempoChangesGeneral, label)) {
+            this.tempoInBpm = 0;
+            this.tempoEnum = TempoEnum.changes;
+        }
+    }
+}
+export enum TempoEnum {
+    none,
+    larghissimo,
+    grave,
+    lento,
+    largo,
+    larghetto,
+    adagio,
+    adagietto,
+    andanteModerato,
+    andante,
+    andantino,
+    moderato,
+    allegretto,
+    allegroModerato,
+    allegro,
+    vivace,
+    vivacissimo,
+    allegrissimo,
+    presto,
+    prestissimo,
+    lastRealTempo,
+    addon,
+    changes
+}

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

@@ -0,0 +1,285 @@
+import {PlacementEnum, AbstractExpression} from "./abstractExpression";
+export class MoodExpression extends AbstractExpression {
+    constructor(label: string, placement: PlacementEnum, staffNumber: number) {
+        this.label = label;
+        this.placement = placement;
+        this.staffNumber = staffNumber;
+        this.setMoodType();
+    }
+    private moodType: MoodEnum;
+    private label: string;
+    private staffNumber: number;
+    private placement: PlacementEnum;
+    static private listMoodAffettuoso: Array<string> = __init(new Array<string>(), { "affettuoso" });
+    static private listMoodAgitato: Array<string> = __init(new Array<string>(), { "agitato" });
+    static private listMoodAppassionato: Array<string> = __init(new Array<string>(), { "appassionato" });
+    static private listMoodAnimato: Array<string> = __init(new Array<string>(), { "animato","lively" });
+    static private listMoodBrillante: Array<string> = __init(new Array<string>(), { "brillante" });
+    static private listMoodCantabile: Array<string> = __init(new Array<string>(), { "cantabile" });
+    static private listMoodDolce: Array<string> = __init(new Array<string>(), { "dolce" });
+    static private listMoodEnergico: Array<string> = __init(new Array<string>(), { "energico" });
+    static private listMoodEroico: Array<string> = __init(new Array<string>(), { "eroico" });
+    static private listMoodEspressivo: Array<string> = __init(new Array<string>(), { "espressivo" });
+    static private listMoodFurioso: Array<string> = __init(new Array<string>(), { "furioso" });
+    static private listMoodGiocoso: Array<string> = __init(new Array<string>(), { "giocoso" });
+    static private listMoodGioioso: Array<string> = __init(new Array<string>(), { "gioioso" });
+    static private listMoodLacrimoso: Array<string> = __init(new Array<string>(), { "lacrimoso" });
+    static private listMoodGrandioso: Array<string> = __init(new Array<string>(), { "grandioso" });
+    static private listMoodGrazioso: Array<string> = __init(new Array<string>(), { "grazioso" });
+    static private listMoodLeggiero: Array<string> = __init(new Array<string>(), { "leggiero" });
+    static private listMoodMaestoso: Array<string> = __init(new Array<string>(), { "maestoso" });
+    static private listMoodMalinconico: Array<string> = __init(new Array<string>(), { "malinconico" });
+    static private listMoodMarcato: Array<string> = __init(new Array<string>(), { "marcato" });
+    static private listMoodMarziale: Array<string> = __init(new Array<string>(), { "marziale" });
+    static private listMoodMesto: Array<string> = __init(new Array<string>(), { "mesto" });
+    static private listMoodMorendo: Array<string> = __init(new Array<string>(), { "morendo" });
+    static private listMoodNobilmente: Array<string> = __init(new Array<string>(), { "nobilmente" });
+    static private listMoodPatetico: Array<string> = __init(new Array<string>(), { "patetico" });
+    static private listMoodPesante: Array<string> = __init(new Array<string>(), { "pesante" });
+    static private listMoodSautille: Array<string> = __init(new Array<string>(), { "sautille" });
+    static private listMoodSaltando: Array<string> = __init(new Array<string>(), { "saltando" });
+    static private listMoodScherzando: Array<string> = __init(new Array<string>(), { "scherzando" });
+    static private listMoodSostenuto: Array<string> = __init(new Array<string>(), { "sostenuto" });
+    static private listMoodSpiccato: Array<string> = __init(new Array<string>(), { "spiccato" });
+    static private listMoodTenerezza: Array<string> = __init(new Array<string>(), { "tenerezza" });
+    static private listMoodTranquillamente: Array<string> = __init(new Array<string>(), { "tranquillamente" });
+    static private listMoodTrionfante: Array<string> = __init(new Array<string>(), { "trionfante" });
+    public get Label(): string {
+        return this.label;
+    }
+    public set Label(value: string) {
+        this.label = value;
+    }
+    public get Mood(): MoodEnum {
+        return this.moodType;
+    }
+    public set Mood(value: MoodEnum) {
+        this.moodType = value;
+    }
+    public get StaffNumber(): number {
+        return this.staffNumber;
+    }
+    public set StaffNumber(value: number) {
+        this.staffNumber = value;
+    }
+    public get Placement(): PlacementEnum {
+        return this.placement;
+    }
+    public set Placement(value: PlacementEnum) {
+        this.placement = value;
+    }
+    public static isInputStringMood(inputString: string): boolean {
+        if (inputString == null)
+            return false;
+        if (isStringInStringList(MoodExpression.listMoodAffettuoso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodAgitato, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodAnimato, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodAppassionato, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodBrillante, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodCantabile, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodDolce, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodEnergico, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodEroico, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodEspressivo, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodFurioso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodGiocoso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodGioioso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodGrandioso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodGrazioso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodLacrimoso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodLeggiero, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodMaestoso, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodMalinconico, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodMarcato, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodMarziale, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodMesto, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodMorendo, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodNobilmente, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodPatetico, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodPesante, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodSaltando, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodSautille, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodScherzando, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodSostenuto, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodSpiccato, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodTenerezza, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodTranquillamente, inputString))
+            return true;
+        if (isStringInStringList(MoodExpression.listMoodTrionfante, inputString))
+            return true;
+        return false;
+    }
+    private setMoodType(): void {
+        if (isStringInStringList(MoodExpression.listMoodAffettuoso, this.label))
+            this.moodType = MoodEnum.Affettuoso;
+        if (isStringInStringList(MoodExpression.listMoodAgitato, this.label))
+            this.moodType = MoodEnum.Agitato;
+        if (isStringInStringList(MoodExpression.listMoodAnimato, this.label))
+            this.moodType = MoodEnum.Animato;
+        if (isStringInStringList(MoodExpression.listMoodAppassionato, this.label))
+            this.moodType = MoodEnum.Appassionato;
+        if (isStringInStringList(MoodExpression.listMoodBrillante, this.label))
+            this.moodType = MoodEnum.Brillante;
+        if (isStringInStringList(MoodExpression.listMoodCantabile, this.label))
+            this.moodType = MoodEnum.Cantabile;
+        if (isStringInStringList(MoodExpression.listMoodDolce, this.label))
+            this.moodType = MoodEnum.Dolce;
+        if (isStringInStringList(MoodExpression.listMoodEnergico, this.label))
+            this.moodType = MoodEnum.Energico;
+        if (isStringInStringList(MoodExpression.listMoodEroico, this.label))
+            this.moodType = MoodEnum.Eroico;
+        if (isStringInStringList(MoodExpression.listMoodEspressivo, this.label))
+            this.moodType = MoodEnum.Espressivo;
+        if (isStringInStringList(MoodExpression.listMoodFurioso, this.label))
+            this.moodType = MoodEnum.Furioso;
+        if (isStringInStringList(MoodExpression.listMoodGiocoso, this.label))
+            this.moodType = MoodEnum.Giocoso;
+        if (isStringInStringList(MoodExpression.listMoodGioioso, this.label))
+            this.moodType = MoodEnum.Gioioso;
+        if (isStringInStringList(MoodExpression.listMoodGrandioso, this.label))
+            this.moodType = MoodEnum.Grandioso;
+        if (isStringInStringList(MoodExpression.listMoodGrazioso, this.label))
+            this.moodType = MoodEnum.Grazioso;
+        if (isStringInStringList(MoodExpression.listMoodLacrimoso, this.label))
+            this.moodType = MoodEnum.Lacrimoso;
+        if (isStringInStringList(MoodExpression.listMoodLeggiero, this.label))
+            this.moodType = MoodEnum.Leggiero;
+        if (isStringInStringList(MoodExpression.listMoodMaestoso, this.label))
+            this.moodType = MoodEnum.Maestoso;
+        if (isStringInStringList(MoodExpression.listMoodMalinconico, this.label))
+            this.moodType = MoodEnum.Malinconico;
+        if (isStringInStringList(MoodExpression.listMoodMarcato, this.label))
+            this.moodType = MoodEnum.Marcato;
+        if (isStringInStringList(MoodExpression.listMoodMarziale, this.label))
+            this.moodType = MoodEnum.Marziale;
+        if (isStringInStringList(MoodExpression.listMoodMesto, this.label))
+            this.moodType = MoodEnum.Mesto;
+        if (isStringInStringList(MoodExpression.listMoodMorendo, this.label))
+            this.moodType = MoodEnum.Morendo;
+        if (isStringInStringList(MoodExpression.listMoodNobilmente, this.label))
+            this.moodType = MoodEnum.Nobilmente;
+        if (isStringInStringList(MoodExpression.listMoodPatetico, this.label))
+            this.moodType = MoodEnum.Patetico;
+        if (isStringInStringList(MoodExpression.listMoodPesante, this.label))
+            this.moodType = MoodEnum.Pesante;
+        if (isStringInStringList(MoodExpression.listMoodSaltando, this.label))
+            this.moodType = MoodEnum.Saltando;
+        if (isStringInStringList(MoodExpression.listMoodSautille, this.label))
+            this.moodType = MoodEnum.Sautille;
+        if (isStringInStringList(MoodExpression.listMoodScherzando, this.label))
+            this.moodType = MoodEnum.Scherzando;
+        if (isStringInStringList(MoodExpression.listMoodSostenuto, this.label))
+            this.moodType = MoodEnum.Sostenuto;
+        if (isStringInStringList(MoodExpression.listMoodSpiccato, this.label))
+            this.moodType = MoodEnum.Spiccato;
+        if (isStringInStringList(MoodExpression.listMoodTenerezza, this.label))
+            this.moodType = MoodEnum.Tenerezza;
+        if (isStringInStringList(MoodExpression.listMoodTranquillamente, this.label))
+            this.moodType = MoodEnum.Tranquillamente;
+        if (isStringInStringList(MoodExpression.listMoodTrionfante, this.label))
+            this.moodType = MoodEnum.Trionfante;
+    }
+}
+export enum MoodEnum {
+    Affettuoso = 0,
+
+    Agitato = 1,
+
+    Appassionato = 2,
+
+    Animato = 3,
+
+    Brillante = 4,
+
+    Cantabile = 5,
+
+    Dolce = 6,
+
+    Energico = 7,
+
+    Eroico = 8,
+
+    Espressivo = 9,
+
+    Furioso = 10,
+
+    Giocoso = 11,
+
+    Gioioso = 12,
+
+    Lacrimoso = 13,
+
+    Grandioso = 14,
+
+    Grazioso = 15,
+
+    Leggiero = 16,
+
+    Maestoso = 17,
+
+    Malinconico = 18,
+
+    Marcato = 19,
+
+    Marziale = 20,
+
+    Mesto = 21,
+
+    Morendo = 22,
+
+    Nobilmente = 23,
+
+    Patetico = 24,
+
+    Pesante = 25,
+
+    Sautille = 26,
+
+    Saltando = 27,
+
+    Scherzando = 28,
+
+    Sostenuto = 29,
+
+    Spiccato = 30,
+
+    Tenerezza = 31,
+
+    Tranquillamente = 32,
+
+    Trionfante = 33,
+
+    Vivace = 34
+}

+ 184 - 0
src/MusicalScore/VoiceData/Expressions/multiExpression.ts

@@ -0,0 +1,184 @@
+export class MultiExpression implements IComparable<MultiExpression>
+{
+    constructor(sourceMeasure: SourceMeasure, timestamp: Fraction) {
+        this.sourceMeasure = sourceMeasure;
+        this.timestamp = timestamp;
+    }
+    private sourceMeasure: SourceMeasure;
+    private staffNumber: number;
+    private timestamp: Fraction;
+    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 combinedExpressionsText: string;
+    private octaveShiftStart: OctaveShift;
+    private octaveShiftEnd: OctaveShift;
+    public get SourceMeasureParent(): SourceMeasure {
+        return this.sourceMeasure;
+    }
+    public set SourceMeasureParent(value: SourceMeasure) {
+        this.sourceMeasure = value;
+    }
+    public get StaffNumber(): number {
+        return this.staffNumber;
+    }
+    public set StaffNumber(value: number) {
+        this.staffNumber = value;
+    }
+    public get Timestamp(): Fraction {
+        return this.timestamp;
+    }
+    public set Timestamp(value: Fraction) {
+        this.timestamp = value;
+    }
+    public get AbsoluteTimestamp(): Fraction {
+        return this.timestamp + this.sourceMeasure.AbsoluteTimestamp;
+    }
+    public get InstantaniousDynamic(): InstantaniousDynamicExpression {
+        return this.instantaniousDynamic;
+    }
+    public set InstantaniousDynamic(value: InstantaniousDynamicExpression) {
+        this.instantaniousDynamic = value;
+    }
+    public get EndingContinuousDynamic(): ContinuousDynamicExpression {
+        return this.endingContinuousDynamic;
+    }
+    public set EndingContinuousDynamic(value: ContinuousDynamicExpression) {
+        this.endingContinuousDynamic = value;
+    }
+    public get StartingContinuousDynamic(): ContinuousDynamicExpression {
+        return this.startingContinuousDynamic;
+    }
+    public set StartingContinuousDynamic(value: ContinuousDynamicExpression) {
+        this.startingContinuousDynamic = value;
+    }
+    public get MoodList(): List<MoodExpression> {
+        return this.moodList;
+    }
+    public get UnknownList(): List<UnknownExpression> {
+        return this.unknownList;
+    }
+    public get EntriesList(): List<MultiExpressionEntry> {
+        return this.expressions;
+    }
+    public get OctaveShiftStart(): OctaveShift {
+        return this.octaveShiftStart;
+    }
+    public set OctaveShiftStart(value: OctaveShift) {
+        this.octaveShiftStart = value;
+    }
+    public get OctaveShiftEnd(): OctaveShift {
+        return this.octaveShiftEnd;
+    }
+    public set OctaveShiftEnd(value: OctaveShift) {
+        this.octaveShiftEnd = value;
+    }
+    public get CombinedExpressionsText(): string {
+        return this.combinedExpressionsText;
+    }
+    public set CombinedExpressionsText(value: string) {
+        this.combinedExpressionsText = value;
+    }
+    public getPlacementOfFirstEntry(): PlacementEnum {
+        var placement: PlacementEnum = PlacementEnum.Above;
+        if (this.expressions.Count > 0) {
+            if (this.expressions[0].expression instanceof InstantaniousDynamicExpression)
+                placement = (<InstantaniousDynamicExpression>(this.expressions[0].expression)).Placement;
+            else if (this.expressions[0].expression instanceof ContinuousDynamicExpression)
+                placement = (<ContinuousDynamicExpression>(this.expressions[0].expression)).Placement;
+            else if (this.expressions[0].expression instanceof MoodExpression)
+                placement = (<MoodExpression>(this.expressions[0].expression)).Placement;
+            else if (this.expressions[0].expression instanceof UnknownExpression)
+                placement = (<UnknownExpression>(this.expressions[0].expression)).Placement;
+        }
+        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 addExpression(abstractExpression: AbstractExpression, prefix: string): void {
+        if (abstractExpression instanceof InstantaniousDynamicExpression) {
+            if (this.instantaniousDynamic != null)
+                removeExpressionFromEntryList(this.InstantaniousDynamic);
+            this.instantaniousDynamic = <InstantaniousDynamicExpression>abstractExpression;
+            this.instantaniousDynamic.ParentMultiExpression = this;
+        }
+        else if (abstractExpression instanceof ContinuousDynamicExpression) {
+            this.startingContinuousDynamic = <ContinuousDynamicExpression>abstractExpression;
+        }
+        else if (abstractExpression instanceof MoodExpression) {
+            this.moodList.Add(<MoodExpression>abstractExpression);
+        }
+        else if (abstractExpression instanceof UnknownExpression) {
+            this.unknownList.Add(<UnknownExpression>abstractExpression);
+        }
+        this.addExpressionToEntryList(abstractExpression, prefix);
+    }
+    public CompareTo(other: MultiExpression): number {
+        if (this.SourceMeasureParent.MeasureNumber > other.SourceMeasureParent.MeasureNumber)
+            return 1;
+        if (this.SourceMeasureParent.MeasureNumber < other.SourceMeasureParent.MeasureNumber)
+            return -1;
+        else {
+            if (this.Timestamp.RealValue > other.Timestamp.RealValue)
+                return 1;
+            if (this.Timestamp.RealValue < other.Timestamp.RealValue)
+                return -1;
+            else return 0;
+        }
+    }
+    private addExpressionToEntryList(expression: AbstractExpression, prefix: string): void {
+        var multiExpressionEntry: MultiExpressionEntry = new MultiExpressionEntry();
+        multiExpressionEntry.prefix = prefix;
+        multiExpressionEntry.expression = expression;
+        if (expression instanceof ContinuousDynamicExpression)
+            multiExpressionEntry.label = (<ContinuousDynamicExpression>(expression)).Label;
+        else if (expression instanceof MoodExpression)
+            multiExpressionEntry.label = (<MoodExpression>(expression)).Label;
+        else if (expression instanceof UnknownExpression)
+            multiExpressionEntry.label = (<UnknownExpression>(expression)).Label;
+        else multiExpressionEntry.label = "";
+        this.expressions.Add(multiExpressionEntry);
+    }
+    private removeExpressionFromEntryList(expression: AbstractExpression): void {
+        for (var idx: number = 0, len = this.expressions.Count; idx < len; ++idx) {
+            var entry: MultiExpressionEntry = this.expressions[idx];
+            if (entry.expression == expression) {
+                this.expressions.Remove(entry);
+                break;
+            }
+        }
+    }
+}
+export class MultiExpressionEntry {
+    public prefix: string;
+    public expression: AbstractExpression;
+    public label: string;
+}

+ 108 - 0
src/MusicalScore/VoiceData/Expressions/multiTempoExpression.ts

@@ -0,0 +1,108 @@
+import {Fraction} from "../../../Common/DataObjects/fraction";
+import {SourceMeasure} from "../SourceMeasure";
+import {InstantaniousTempoExpression} from "./instantaniousTempoExpression";
+import {PlacementEnum} from "./abstractExpression";
+import {OSMDFontStyles} from "../../../Common/Enums/osmdFontStyles";
+import {AbstractTempoExpression} from "./abstractTempoExpression";
+import {ContinuousTempoExpression} from "./ContinuousExpressions/continuousTempoExpression";
+
+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 combinedExpressionsText: string;
+    public get Timestamp(): Fraction {
+        return this.timestamp;
+    }
+    public get AbsoluteTimestamp(): Fraction {
+        return this.sourceMeasure.AbsoluteTimestamp + this.timestamp;
+    }
+    public get SourceMeasureParent(): SourceMeasure {
+        return this.sourceMeasure;
+    }
+    public set SourceMeasureParent(value: SourceMeasure) {
+        this.sourceMeasure = value;
+    }
+    public get InstantaniousTempo(): InstantaniousTempoExpression {
+        return this.instantaniousTempo;
+    }
+    public get ContinuousTempo(): ContinuousTempoExpression {
+        return this.continuousTempo;
+    }
+    public get EntriesList(): Array<TempoExpressionEntry> {
+        return this.expressions;
+    }
+    public get CombinedExpressionsText(): string {
+        return this.combinedExpressionsText;
+    }
+    public set CombinedExpressionsText(value: string) {
+        this.combinedExpressionsText = value;
+    }
+    public getPlacementOfFirstEntry(): PlacementEnum {
+        var placement: PlacementEnum = PlacementEnum.Above;
+        if (this.expressions.length > 0) {
+            if (this.expressions[0].expression instanceof InstantaniousTempoExpression)
+                placement = (<InstantaniousTempoExpression>(this.expressions[0].expression)).Placement;
+            else if (this.expressions[0].expression instanceof ContinuousTempoExpression)
+                placement = (<ContinuousTempoExpression>(this.expressions[0].expression)).Placement;
+        }
+        return placement;
+    }
+    public getFontstyleOfFirstEntry(): OSMDFontStyles {
+        var fontStyle: OSMDFontStyles = OSMDFontStyles.Regular;
+        if (this.expressions[0].expression instanceof InstantaniousTempoExpression)
+            fontStyle = OSMDFontStyles.Bold;
+        else if (this.expressions[0].expression instanceof ContinuousTempoExpression)
+            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 addExpression(abstractTempoExpression: AbstractTempoExpression, prefix: string): void {
+        if (abstractTempoExpression instanceof InstantaniousTempoExpression) {
+            this.instantaniousTempo = <InstantaniousTempoExpression>abstractTempoExpression;
+        }
+        else if (abstractTempoExpression instanceof ContinuousTempoExpression) {
+            this.continuousTempo = <ContinuousTempoExpression>abstractTempoExpression;
+        }
+        var tempoExpressionEntry: TempoExpressionEntry = new TempoExpressionEntry();
+        tempoExpressionEntry.prefix = prefix;
+        tempoExpressionEntry.expression = abstractTempoExpression;
+        tempoExpressionEntry.label = abstractTempoExpression.Label;
+        this.expressions.push(tempoExpressionEntry);
+    }
+    public CompareTo(other: MultiTempoExpression): number {
+        if (this.SourceMeasureParent.MeasureNumber > other.SourceMeasureParent.MeasureNumber)
+            return 1;
+        if (this.SourceMeasureParent.MeasureNumber < other.SourceMeasureParent.MeasureNumber)
+            return -1;
+        else {
+            if (this.Timestamp.RealValue > other.Timestamp.RealValue)
+                return 1;
+            if (this.Timestamp.RealValue < other.Timestamp.RealValue)
+                return -1;
+            else return 0;
+        }
+    }
+}
+export class TempoExpressionEntry {
+    public prefix: string;
+    public expression: AbstractTempoExpression;
+    public label: string;
+}

+ 36 - 0
src/MusicalScore/VoiceData/Expressions/unknownExpression.ts

@@ -0,0 +1,36 @@
+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);
+
+    }
+    constructor(label: string, placementEnum: PlacementEnum, textAlignment: OSMDTextAlignment, staffNumber: number) {
+        this.label = label;
+        this.placement = placementEnum;
+        this.staffNumber = staffNumber;
+        this.textAlignment = textAlignment;
+    }
+    private label: string;
+    private placement: PlacementEnum;
+    private textAlignment: OSMDTextAlignment;
+    private staffNumber: number;
+    public get Label(): string {
+        return this.label;
+    }
+    public get Placement(): PlacementEnum {
+        return this.placement;
+    }
+    public set Placement(value: PlacementEnum) {
+        this.placement = value;
+    }
+    public get StaffNumber(): number {
+        return this.staffNumber;
+    }
+    public set StaffNumber(value: number) {
+        this.staffNumber = value;
+    }
+    public get TextAlignment(): OSMDTextAlignment {
+        return this.textAlignment;
+    }
+}