|
@@ -31,7 +31,7 @@ export class ExpressionReader {
|
|
|
private globalStaffIndex: number;
|
|
|
private directionTimestamp: Fraction;
|
|
|
private currentMultiTempoExpression: MultiTempoExpression;
|
|
|
- private openContinuousDynamicExpression: ContinuousDynamicExpression;
|
|
|
+ private openContinuousDynamicExpressions: ContinuousDynamicExpression[] = [];
|
|
|
private openContinuousTempoExpression: ContinuousTempoExpression;
|
|
|
private activeInstantaneousDynamic: InstantaneousDynamicExpression;
|
|
|
private openOctaveShift: OctaveShift;
|
|
@@ -249,10 +249,13 @@ export class ExpressionReader {
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
- public checkForOpenExpressions(sourceMeasure: SourceMeasure, timestamp: Fraction): void {
|
|
|
- if (this.openContinuousDynamicExpression) {
|
|
|
- this.createNewMultiExpressionIfNeeded(sourceMeasure, timestamp);
|
|
|
- this.closeOpenContinuousDynamic();
|
|
|
+ /** Usually called at end of last measure. */
|
|
|
+ public closeOpenExpressions(sourceMeasure: SourceMeasure, timestamp: Fraction): void {
|
|
|
+ for (const openCont of this.openContinuousDynamicExpressions) {
|
|
|
+ // add to current stafflinked expression // refactor into closeOpenContinuousDynamic?
|
|
|
+ this.createNewMultiExpressionIfNeeded(sourceMeasure, openCont.NumberXml, timestamp);
|
|
|
+
|
|
|
+ this.closeOpenContinuousDynamic(openCont, sourceMeasure, timestamp);
|
|
|
}
|
|
|
if (this.openContinuousTempoExpression) {
|
|
|
this.closeOpenContinuousTempo(Fraction.plus(sourceMeasure.AbsoluteTimestamp, timestamp));
|
|
@@ -275,8 +278,13 @@ export class ExpressionReader {
|
|
|
const directionTypeNode: IXmlElement = directionNode.element("direction-type");
|
|
|
if (directionTypeNode) {
|
|
|
const octaveShiftNode: IXmlElement = directionTypeNode.element("octave-shift");
|
|
|
+ const placement: PlacementEnum = this.readPlacement(directionNode);
|
|
|
+ // if (placement === PlacementEnum.NotYetDefined && this.staffNumber === 1) {
|
|
|
+ // placement = PlacementEnum.Above;
|
|
|
+ // }
|
|
|
if (octaveShiftNode !== undefined && octaveShiftNode.hasAttributes) {
|
|
|
try {
|
|
|
+ const numberXml: number = this.readNumber(octaveShiftNode);
|
|
|
if (octaveShiftNode.attribute("size")) {
|
|
|
const size: number = parseInt(octaveShiftNode.attribute("size").value, 10);
|
|
|
let octave: number = 0;
|
|
@@ -285,23 +293,34 @@ export class ExpressionReader {
|
|
|
} else if (size === 15) {
|
|
|
octave = 2;
|
|
|
}
|
|
|
- if (octaveShiftNode.attribute("type")) {
|
|
|
- const type: string = octaveShiftNode.attribute("type").value;
|
|
|
- if (type === "up" || type === "down") {
|
|
|
- const octaveShift: OctaveShift = new OctaveShift(type, octave);
|
|
|
- octaveShift.StaffNumber = octaveStaffNumber;
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
- this.getMultiExpression.OctaveShiftStart = octaveShift;
|
|
|
- octaveShift.ParentStartMultiExpression = this.getMultiExpression;
|
|
|
- this.openOctaveShift = octaveShift;
|
|
|
- } else if (type === "stop") {
|
|
|
- if (this.openOctaveShift) {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure, endTimestamp);
|
|
|
- this.getMultiExpression.OctaveShiftEnd = this.openOctaveShift;
|
|
|
- this.openOctaveShift.ParentEndMultiExpression = this.getMultiExpression;
|
|
|
- this.openOctaveShift = undefined;
|
|
|
- }
|
|
|
+ let type: string = octaveShiftNode.attribute("type")?.value;
|
|
|
+ if (!type) {
|
|
|
+ if (placement === PlacementEnum.Above) {
|
|
|
+ type = "down";
|
|
|
+ } else if (placement === PlacementEnum.Below) {
|
|
|
+ type = "up";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (type === "up" || type === "down") { // unfortunately not always given in MusicXML (e.g. Musescore 3.6.2) even though required
|
|
|
+ const octaveShift: OctaveShift = new OctaveShift(type, octave);
|
|
|
+ octaveShift.StaffNumber = octaveStaffNumber;
|
|
|
+ this.getMultiExpression = this.createNewMultiExpressionIfNeeded(
|
|
|
+ currentMeasure, numberXml);
|
|
|
+ this.getMultiExpression.OctaveShiftStart = octaveShift;
|
|
|
+ octaveShift.ParentStartMultiExpression = this.getMultiExpression;
|
|
|
+ this.openOctaveShift = octaveShift;
|
|
|
+ } else if (type === "stop") {
|
|
|
+ if (this.openOctaveShift) {
|
|
|
+ this.getMultiExpression = this.createNewMultiExpressionIfNeeded(
|
|
|
+ currentMeasure, this.openOctaveShift.numberXml, endTimestamp);
|
|
|
+ const octaveShiftStartExpression: MultiExpression = this.getMultiExpression;
|
|
|
+ octaveShiftStartExpression.OctaveShiftEnd = this.openOctaveShift;
|
|
|
+ this.openOctaveShift.ParentEndMultiExpression = this.getMultiExpression;
|
|
|
+ this.openOctaveShift = undefined;
|
|
|
}
|
|
|
+ } // TODO handle type === "continue"?
|
|
|
+ else if (!type) {
|
|
|
+ log.debug("octave-shift missing type in xml");
|
|
|
}
|
|
|
}
|
|
|
} catch (ex) {
|
|
@@ -337,7 +356,7 @@ export class ExpressionReader {
|
|
|
case "start":
|
|
|
//ignore duplicate tags
|
|
|
if (!this.openPedal || !this.openPedal.ParentStartMultiExpression.AbsoluteTimestamp.Equals(endTimestamp)) {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
}
|
|
|
this.openPedal = new Pedal(line, sign);
|
|
|
this.getMultiExpression.PedalStart = this.openPedal;
|
|
@@ -345,7 +364,7 @@ export class ExpressionReader {
|
|
|
break;
|
|
|
case "stop":
|
|
|
if (this.openPedal) {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
this.getMultiExpression.PedalEnd = this.openPedal;
|
|
|
this.openPedal.ParentEndMultiExpression = this.getMultiExpression;
|
|
|
this.openPedal = undefined;
|
|
@@ -355,11 +374,11 @@ export class ExpressionReader {
|
|
|
//Ignore non-line pedals
|
|
|
if (this.openPedal && this.openPedal.IsLine) {
|
|
|
this.openPedal.ChangeEnd = true;
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
this.getMultiExpression.PedalEnd = this.openPedal;
|
|
|
this.openPedal.ParentEndMultiExpression = this.getMultiExpression;
|
|
|
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
this.openPedal = new Pedal(line, sign);
|
|
|
this.openPedal.ChangeBegin = true;
|
|
|
this.getMultiExpression.PedalStart = this.openPedal;
|
|
@@ -384,14 +403,14 @@ export class ExpressionReader {
|
|
|
try {
|
|
|
switch (wavyLineNode.attribute("type").value) {
|
|
|
case "start":
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
this.openWavyLine = new WavyLine(this.placement);
|
|
|
this.getMultiExpression.WavyLineStart = this.openWavyLine;
|
|
|
this.openWavyLine.ParentStartMultiExpression = this.getMultiExpression;
|
|
|
break;
|
|
|
case "stop":
|
|
|
if (this.openWavyLine) {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure, currentTimestamp);
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, -1, currentTimestamp);
|
|
|
this.getMultiExpression.WavyLineEnd = this.openWavyLine;
|
|
|
this.openWavyLine.ParentEndMultiExpression = this.getMultiExpression;
|
|
|
this.openWavyLine = undefined;
|
|
@@ -416,6 +435,16 @@ export class ExpressionReader {
|
|
|
this.soundDynamic = 0;
|
|
|
this.offsetDivisions = 0;
|
|
|
}
|
|
|
+ private readPlacement(node: IXmlElement): PlacementEnum {
|
|
|
+ const value: string = node.attribute("placement")?.value;
|
|
|
+ if (value === "above") {
|
|
|
+ return PlacementEnum.Above;
|
|
|
+ } else if (value === "below") {
|
|
|
+ return PlacementEnum.Below;
|
|
|
+ } else {
|
|
|
+ return PlacementEnum.NotYetDefined;
|
|
|
+ }
|
|
|
+ }
|
|
|
private readExpressionPlacement(defAttr: IXmlAttribute, catchLogMessage: string): void {
|
|
|
try {
|
|
|
const y: number = parseInt(defAttr.value, 10);
|
|
@@ -437,6 +466,7 @@ export class ExpressionReader {
|
|
|
if (dynamicsNode.hasAttributes && dynamicsNode.attribute("default-x")) {
|
|
|
this.directionTimestamp = Fraction.createFromFraction(inSourceMeasureCurrentFraction);
|
|
|
}
|
|
|
+ const numberXml: number = this.readNumber(dynamicsNode); // probably never given, just to comply with createExpressionIfNeeded()
|
|
|
let expressionText: string = dynamicsNode.elements()[0].name;
|
|
|
if (expressionText === "other-dynamics") {
|
|
|
expressionText = dynamicsNode.elements()[0].value;
|
|
@@ -457,11 +487,10 @@ export class ExpressionReader {
|
|
|
// if (!this.activeInstantaneousDynamic ||
|
|
|
// (this.activeInstantaneousDynamic && this.activeInstantaneousDynamic.DynEnum !== dynamicEnum)) {
|
|
|
if (!fromNotation) {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
- } else { this.createNewMultiExpressionIfNeeded(currentMeasure, Fraction.createFromFraction(inSourceMeasureCurrentFraction)); }
|
|
|
- if (this.openContinuousDynamicExpression !== undefined &&
|
|
|
- this.openContinuousDynamicExpression.StartMultiExpression !== this.getMultiExpression) {
|
|
|
- this.closeOpenContinuousDynamic();
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, numberXml);
|
|
|
+ } else {
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, numberXml,
|
|
|
+ Fraction.createFromFraction(inSourceMeasureCurrentFraction));
|
|
|
}
|
|
|
const instantaneousDynamicExpression: InstantaneousDynamicExpression =
|
|
|
new InstantaneousDynamicExpression(
|
|
@@ -470,7 +499,11 @@ export class ExpressionReader {
|
|
|
this.placement,
|
|
|
this.staffNumber,
|
|
|
currentMeasure);
|
|
|
+ instantaneousDynamicExpression.InMeasureTimestamp = inSourceMeasureCurrentFraction.clone();
|
|
|
this.getMultiExpression.addExpression(instantaneousDynamicExpression, "");
|
|
|
+ // addExpression unnecessary now?:
|
|
|
+ //const multiExpression = this.getMultiExpression(ExpressionType.InstantaneousDynamic, numberXml);
|
|
|
+ //multiExpression.addExpression(instantaneousDynamicExpression, "");
|
|
|
this.initialize();
|
|
|
if (this.activeInstantaneousDynamic) {
|
|
|
this.activeInstantaneousDynamic.DynEnum = instantaneousDynamicExpression.DynEnum;
|
|
@@ -498,22 +531,31 @@ export class ExpressionReader {
|
|
|
if (this.checkIfWordsNodeIsRepetitionInstruction(text)) {
|
|
|
return;
|
|
|
}
|
|
|
- this.fillMultiOrTempoExpression(text, currentMeasure, fontStyle);
|
|
|
+ this.fillMultiOrTempoExpression(text, currentMeasure, inSourceMeasureCurrentFraction, fontStyle);
|
|
|
this.initialize();
|
|
|
}
|
|
|
}
|
|
|
+ private readNumber(node: IXmlElement): number {
|
|
|
+ let numberXml: number = 1; // default value
|
|
|
+ const numberStringXml: string = node.attribute("number")?.value;
|
|
|
+ if (numberStringXml) {
|
|
|
+ numberXml = Number.parseInt(numberStringXml, 10);
|
|
|
+ }
|
|
|
+ return numberXml;
|
|
|
+ }
|
|
|
private interpretWedge(wedgeNode: IXmlElement, currentMeasure: SourceMeasure, inSourceMeasureCurrentFraction: Fraction, currentMeasureIndex: number): void {
|
|
|
if (wedgeNode !== undefined && wedgeNode.hasAttributes && wedgeNode.attribute("default-x")) {
|
|
|
this.directionTimestamp = Fraction.createFromFraction(inSourceMeasureCurrentFraction);
|
|
|
}
|
|
|
+ const wedgeNumberXml: number = this.readNumber(wedgeNode);
|
|
|
//Ending needs to use previous fraction, not current.
|
|
|
//If current is used, when there is a system break it will mess up
|
|
|
- if (wedgeNode?.attribute("type")?.value?.toLowerCase() === "stop") {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure, inSourceMeasureCurrentFraction);
|
|
|
+ if (wedgeNode.attribute("type")?.value?.toLowerCase() === "stop") {
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, wedgeNumberXml, inSourceMeasureCurrentFraction);
|
|
|
} else {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, wedgeNumberXml);
|
|
|
}
|
|
|
- this.addWedge(wedgeNode, currentMeasure);
|
|
|
+ this.addWedge(wedgeNode, currentMeasure, inSourceMeasureCurrentFraction);
|
|
|
this.initialize();
|
|
|
}
|
|
|
private interpretRehearsalMark(
|
|
@@ -522,17 +564,21 @@ export class ExpressionReader {
|
|
|
// TODO create multi expression? for now we just need to have a static rehearsal mark though.
|
|
|
currentMeasure.rehearsalExpression = new RehearsalExpression(rehearsalNode.value, this.placement);
|
|
|
}
|
|
|
- private createNewMultiExpressionIfNeeded(currentMeasure: SourceMeasure, timestamp: Fraction = undefined): void {
|
|
|
+ private createNewMultiExpressionIfNeeded(currentMeasure: SourceMeasure, numberXml: number,
|
|
|
+ timestamp: Fraction = undefined): MultiExpression {
|
|
|
if (!timestamp) {
|
|
|
timestamp = this.directionTimestamp;
|
|
|
}
|
|
|
- if (!this.getMultiExpression ||
|
|
|
- this.getMultiExpression &&
|
|
|
- (this.getMultiExpression.SourceMeasureParent !== currentMeasure ||
|
|
|
- (this.getMultiExpression.SourceMeasureParent === currentMeasure && this.getMultiExpression.Timestamp !== timestamp))) {
|
|
|
- this.getMultiExpression = new MultiExpression(currentMeasure, Fraction.createFromFraction(timestamp));
|
|
|
- currentMeasure.StaffLinkedExpressions[this.globalStaffIndex].push(this.getMultiExpression);
|
|
|
+ let existingMultiExpression: MultiExpression = this.getMultiExpression;
|
|
|
+ if (!existingMultiExpression ||
|
|
|
+ existingMultiExpression &&
|
|
|
+ (existingMultiExpression.SourceMeasureParent !== currentMeasure ||
|
|
|
+ existingMultiExpression.numberXml !== numberXml ||
|
|
|
+ (existingMultiExpression.SourceMeasureParent === currentMeasure && existingMultiExpression.Timestamp !== timestamp))) {
|
|
|
+ this.getMultiExpression = existingMultiExpression = new MultiExpression(currentMeasure, Fraction.createFromFraction(timestamp));
|
|
|
+ currentMeasure.StaffLinkedExpressions[this.globalStaffIndex].push(existingMultiExpression);
|
|
|
}
|
|
|
+ return existingMultiExpression;
|
|
|
}
|
|
|
|
|
|
private createNewTempoExpressionIfNeeded(currentMeasure: SourceMeasure): void {
|
|
@@ -543,8 +589,9 @@ export class ExpressionReader {
|
|
|
currentMeasure.TempoExpressions.push(this.currentMultiTempoExpression);
|
|
|
}
|
|
|
}
|
|
|
- private addWedge(wedgeNode: IXmlElement, currentMeasure: SourceMeasure): void {
|
|
|
+ private addWedge(wedgeNode: IXmlElement, currentMeasure: SourceMeasure, inSourceMeasureCurrentFraction: Fraction): void {
|
|
|
if (wedgeNode !== undefined && wedgeNode.hasAttributes) {
|
|
|
+ const numberXml: number = this.readNumber(wedgeNode);
|
|
|
const type: string = wedgeNode.attribute("type").value.toLowerCase();
|
|
|
try {
|
|
|
if (type === "crescendo" || type === "diminuendo") {
|
|
@@ -554,20 +601,26 @@ export class ExpressionReader {
|
|
|
this.placement,
|
|
|
this.staffNumber,
|
|
|
currentMeasure,
|
|
|
- this.activeInstantaneousDynamic);
|
|
|
- if (this.openContinuousDynamicExpression) {
|
|
|
- this.closeOpenContinuousDynamic();
|
|
|
+ this.activeInstantaneousDynamic,
|
|
|
+ numberXml);
|
|
|
+ this.openContinuousDynamicExpressions.push(continuousDynamicExpression);
|
|
|
+ let multiExpression: MultiExpression = this.getMultiExpression;
|
|
|
+ if (!multiExpression) {
|
|
|
+ multiExpression = this.createNewMultiExpressionIfNeeded(currentMeasure, numberXml);
|
|
|
}
|
|
|
- this.openContinuousDynamicExpression = continuousDynamicExpression;
|
|
|
- this.getMultiExpression.StartingContinuousDynamic = continuousDynamicExpression;
|
|
|
- continuousDynamicExpression.StartMultiExpression = this.getMultiExpression;
|
|
|
+ multiExpression.StartingContinuousDynamic = continuousDynamicExpression;
|
|
|
+ continuousDynamicExpression.StartMultiExpression = multiExpression;
|
|
|
if (this.activeInstantaneousDynamic !== undefined &&
|
|
|
this.activeInstantaneousDynamic.StaffNumber === continuousDynamicExpression.StaffNumber) {
|
|
|
this.activeInstantaneousDynamic = undefined;
|
|
|
}
|
|
|
} else if (type === "stop") {
|
|
|
- if (this.openContinuousDynamicExpression) {
|
|
|
- this.closeOpenContinuousDynamic();
|
|
|
+ for (const openCont of this.openContinuousDynamicExpressions) {
|
|
|
+ if (openCont.NumberXml === numberXml) {
|
|
|
+ if (openCont.NumberXml === numberXml) {
|
|
|
+ this.closeOpenContinuousDynamic(openCont, currentMeasure, inSourceMeasureCurrentFraction);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
} catch (ex) {
|
|
@@ -577,7 +630,8 @@ export class ExpressionReader {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- private fillMultiOrTempoExpression(inputString: string, currentMeasure: SourceMeasure, fontStyle: FontStyles): void {
|
|
|
+ private fillMultiOrTempoExpression(inputString: string, currentMeasure: SourceMeasure, inSourceMeasureCurrentFraction: Fraction,
|
|
|
+ fontStyle: FontStyles): void {
|
|
|
if (!inputString) {
|
|
|
return;
|
|
|
}
|
|
@@ -586,7 +640,7 @@ export class ExpressionReader {
|
|
|
//const splitStrings: string[] = tmpInputString.split(/([\s,\r\n]and[\s,\r\n]|[\s,\r\n]und[\s,\r\n]|[\s,\r\n]e[\s,\r\n]|[\s,\r\n])+/g);
|
|
|
|
|
|
//for (const splitStr of splitStrings) {
|
|
|
- this.createExpressionFromString("", tmpInputString, currentMeasure, inputString, fontStyle);
|
|
|
+ this.createExpressionFromString("", tmpInputString, currentMeasure, inSourceMeasureCurrentFraction, inputString, fontStyle);
|
|
|
//}
|
|
|
}
|
|
|
/*
|
|
@@ -618,7 +672,7 @@ export class ExpressionReader {
|
|
|
}
|
|
|
*/
|
|
|
private createExpressionFromString(prefix: string, stringTrimmed: string,
|
|
|
- currentMeasure: SourceMeasure, inputString: string,
|
|
|
+ currentMeasure: SourceMeasure, inSourceMeasureCurrentFraction, inputString: string,
|
|
|
fontStyle: FontStyles): boolean {
|
|
|
if (InstantaneousTempoExpression.isInputStringInstantaneousTempo(stringTrimmed) ||
|
|
|
ContinuousTempoExpression.isInputStringContinuousTempo(stringTrimmed)) {
|
|
@@ -645,10 +699,11 @@ export class ExpressionReader {
|
|
|
return true;
|
|
|
}
|
|
|
if (ContinuousTempoExpression.isInputStringContinuousTempo(stringTrimmed)) {
|
|
|
- const continuousTempoExpression: ContinuousTempoExpression = new ContinuousTempoExpression( stringTrimmed,
|
|
|
- this.placement,
|
|
|
- this.staffNumber,
|
|
|
- this.currentMultiTempoExpression);
|
|
|
+ const continuousTempoExpression: ContinuousTempoExpression = new ContinuousTempoExpression(
|
|
|
+ stringTrimmed,
|
|
|
+ this.placement,
|
|
|
+ this.staffNumber,
|
|
|
+ this.currentMultiTempoExpression);
|
|
|
this.currentMultiTempoExpression.addExpression(continuousTempoExpression, prefix);
|
|
|
return true;
|
|
|
}
|
|
@@ -656,7 +711,6 @@ export class ExpressionReader {
|
|
|
if (ContinuousDynamicExpression.isInputStringContinuousDynamic(stringTrimmed)) {
|
|
|
// || InstantaneousDynamicExpression.isInputStringInstantaneousDynamic(stringTrimmed)
|
|
|
// looks like <words> never has instantaneous dynamics like p or sf, those are in <dynamics>.
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
// if (InstantaneousDynamicExpression.isInputStringInstantaneousDynamic(stringTrimmed)) {
|
|
|
// if (this.openContinuousDynamicExpression !== undefined && !this.openContinuousDynamicExpression.EndMultiExpression) {
|
|
|
// this.closeOpenContinuousDynamic();
|
|
@@ -679,29 +733,32 @@ export class ExpressionReader {
|
|
|
this.staffNumber,
|
|
|
currentMeasure,
|
|
|
this.activeInstantaneousDynamic,
|
|
|
+ -1,
|
|
|
stringTrimmed);
|
|
|
- if (this.openContinuousDynamicExpression !== undefined && !this.openContinuousDynamicExpression.EndMultiExpression) {
|
|
|
- this.closeOpenContinuousDynamic();
|
|
|
+ const openWordContinuousDynamic: MultiExpression = this.getMultiExpression;
|
|
|
+ if (openWordContinuousDynamic) {
|
|
|
+ this.closeOpenContinuousDynamic(openWordContinuousDynamic.StartingContinuousDynamic, currentMeasure, inSourceMeasureCurrentFraction);
|
|
|
}
|
|
|
+ this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
if (this.activeInstantaneousDynamic !== undefined && this.activeInstantaneousDynamic.StaffNumber === continuousDynamicExpression.StaffNumber) {
|
|
|
this.activeInstantaneousDynamic = undefined;
|
|
|
}
|
|
|
- this.openContinuousDynamicExpression = continuousDynamicExpression;
|
|
|
+ this.openContinuousDynamicExpressions.push(continuousDynamicExpression);
|
|
|
continuousDynamicExpression.StartMultiExpression = this.getMultiExpression;
|
|
|
this.getMultiExpression.addExpression(continuousDynamicExpression, prefix);
|
|
|
return true;
|
|
|
}
|
|
|
if (MoodExpression.isInputStringMood(stringTrimmed)) {
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ const multiExpression: MultiExpression = this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
currentMeasure.hasMoodExpressions = true;
|
|
|
const moodExpression: MoodExpression = new MoodExpression(stringTrimmed, this.placement, this.staffNumber);
|
|
|
moodExpression.fontStyle = fontStyle;
|
|
|
- this.getMultiExpression.addExpression(moodExpression, prefix);
|
|
|
+ multiExpression.addExpression(moodExpression, prefix);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
// create unknown:
|
|
|
- this.createNewMultiExpressionIfNeeded(currentMeasure);
|
|
|
+ const unknownMultiExpression: MultiExpression = this.createNewMultiExpressionIfNeeded(currentMeasure, -1);
|
|
|
// check here first if there might be a tempo expression doublette:
|
|
|
if (currentMeasure.TempoExpressions.length > 0) {
|
|
|
for (let idx: number = 0, len: number = currentMeasure.TempoExpressions.length; idx < len; ++idx) {
|
|
@@ -728,15 +785,20 @@ export class ExpressionReader {
|
|
|
}
|
|
|
const unknownExpression: UnknownExpression = new UnknownExpression(
|
|
|
stringTrimmed, this.placement, textAlignment, this.staffNumber);
|
|
|
- unknownExpression.fontStyle = fontStyle;
|
|
|
- this.getMultiExpression.addExpression(unknownExpression, prefix);
|
|
|
+ unknownExpression.fontStyle = fontStyle;
|
|
|
+ unknownMultiExpression.addExpression(unknownExpression, prefix);
|
|
|
|
|
|
return false;
|
|
|
}
|
|
|
- private closeOpenContinuousDynamic(): void {
|
|
|
- this.openContinuousDynamicExpression.EndMultiExpression = this.getMultiExpression;
|
|
|
- this.getMultiExpression.EndingContinuousDynamic = this.openContinuousDynamicExpression;
|
|
|
- this.openContinuousDynamicExpression = undefined;
|
|
|
+ private closeOpenContinuousDynamic(openContinuousDynamicExpression: ContinuousDynamicExpression, endMeasure: SourceMeasure, timestamp: Fraction): void {
|
|
|
+ if (!openContinuousDynamicExpression) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const numberXml: number = openContinuousDynamicExpression.NumberXml;
|
|
|
+ openContinuousDynamicExpression.EndMultiExpression = this.createNewMultiExpressionIfNeeded(
|
|
|
+ endMeasure, numberXml, timestamp);
|
|
|
+ openContinuousDynamicExpression.StartMultiExpression.EndingContinuousDynamic = openContinuousDynamicExpression;
|
|
|
+ this.openContinuousDynamicExpressions = this.openContinuousDynamicExpressions.filter(dyn => dyn !== openContinuousDynamicExpression);
|
|
|
}
|
|
|
private closeOpenContinuousTempo(endTimestamp: Fraction): void {
|
|
|
this.openContinuousTempoExpression.AbsoluteEndTimestamp = endTimestamp;
|