diff --git a/history.md b/history.md index ecd83c5f..0b2c6ca3 100644 --- a/history.md +++ b/history.md @@ -1,6 +1,10 @@ ### Version History +#### v0.8.32 +- Enhancement/reimplementation of method `meico.mpm.elements.maps.ArticulationMap.renderArticulationToMap_millisecondModifiers()` to allow more extreme delays and duration changes. + + #### v0.8.31 - Reimplementation of method `meico.mpm.elements.maps.AsynchronyMap.renderAsynchronyToMap()`. The previous version did handle some note offsets incorrectly. This is fixed in the new version. diff --git a/src/meico/Meico.java b/src/meico/Meico.java index d2a2880e..c3e6977f 100644 --- a/src/meico/Meico.java +++ b/src/meico/Meico.java @@ -5,7 +5,7 @@ * @author Axel Berndt */ public class Meico { - public static final String version = "0.8.31"; + public static final String version = "0.8.32"; public static void main(String[] args) { System.out.println("meico v" + Meico.version); diff --git a/src/meico/mpm/elements/maps/ArticulationMap.java b/src/meico/mpm/elements/maps/ArticulationMap.java index 4c2a74df..f05e10a2 100644 --- a/src/meico/mpm/elements/maps/ArticulationMap.java +++ b/src/meico/mpm/elements/maps/ArticulationMap.java @@ -504,53 +504,66 @@ public void renderArticulationToMap_millisecondModifiers(GenericMap map) { return; for (KeyValue entry : map.elements) { + // collect all values and remove the temporary modifiers attributes (articulation.) from the xml element Attribute dateAtt = Helper.getAttribute("milliseconds.date", entry.getValue()); if (dateAtt == null) continue; double date = Double.parseDouble(dateAtt.getValue()); + double dateNew = date; Attribute endAtt = Helper.getAttribute("milliseconds.date.end", entry.getValue()); + Double end = null; + if (endAtt != null) + end = Double.parseDouble(endAtt.getValue()); + Double endNew = end; Attribute absoluteDelayMs = Helper.getAttribute("articulation.absoluteDelayMs", entry.getValue()); if (absoluteDelayMs != null) { double delay = Double.parseDouble(absoluteDelayMs.getValue()); - double dateNew = date + delay; - - if (endAtt != null) { - double end = Double.parseDouble(endAtt.getValue()); - if (dateNew >= end) { // if the delay goes beyond the end date of the note - double delayNew = (end - date) / 2.0; - dateNew = date + delayNew; // reduce the delay to half of the time between date and end - System.out.println("Note " + entry.getValue().toXML() + " cannot be delayed by " + delay + " milliseconds. Reducing delay to " + delayNew + " milliseconds."); - } - } - dateAtt.setValue(Double.toString(dateNew)); - -// ((Element)absoluteDelayMs.getParent()).removeAttribute(absoluteDelayMs); + dateNew += delay; + entry.getValue().removeAttribute(absoluteDelayMs); absoluteDelayMs.detach(); } - if (endAtt == null) - continue; - Attribute absoluteDurationMs = Helper.getAttribute("articulation.absoluteDurationMs", entry.getValue()); if (absoluteDurationMs != null) { - endAtt.setValue(Double.toString(date + Double.parseDouble(absoluteDurationMs.getValue()))); -// ((Element)absoluteDurationMs.getParent()).removeAttribute(absoluteDurationMs); + if (endNew != null) { + double dur = Double.parseDouble(absoluteDurationMs.getValue()); + endNew = dateNew + dur; + } + entry.getValue().removeAttribute(absoluteDurationMs); absoluteDurationMs.detach(); } Attribute absoluteDurationChangeMs = Helper.getAttribute("articulation.absoluteDurationChangeMs", entry.getValue()); if (absoluteDurationChangeMs != null) { - double end = Double.parseDouble(endAtt.getValue()); - double durChange = Double.parseDouble(absoluteDurationChangeMs.getValue()); - double endNew = end + durChange; - for (double reduce = 2.0; endNew <= date; reduce *= 2.0) // as long as the duration change causes the duration to become 0.0 or negative - endNew = end + (durChange / reduce); // reduce the change by 50% - endAtt.setValue(Double.toString(endNew)); -// ((Element)absoluteDurationChangeMs.getParent()).removeAttribute(absoluteDurationChangeMs); + if (endNew != null) { + double durChange = Double.parseDouble(absoluteDurationChangeMs.getValue()); + endNew += durChange; + } + entry.getValue().removeAttribute(absoluteDurationChangeMs); absoluteDurationChangeMs.detach(); } + + if ((endNew == null) || (dateNew < endNew)) { // if all is fine + dateAtt.setValue(Double.toString(dateNew)); // set the milliseconds.date attribute + endAtt.setValue(Double.toString(endNew)); // set the milliseconds.date.end attribute + continue; // done with this entry + } + + // if the delay and duration change cause a clash or reversal of onset and offset + System.out.println("Articulation of note " + entry.getValue().toXML() + " causes a clash or reversal of onset (" + date + "->" + dateNew + ") and offset (" + end + "->" + endNew + ")! Reducing the effect of the articulation to resolve the problem."); + double dateAdjust = dateNew; + double endAdjust = endNew; + for (double reduction = 0.5; (dateAdjust >= endAdjust) && (reduction > 0.001); reduction *= 0.5) { + dateAdjust = date + ((dateNew - date) * reduction); + endAdjust = end + ((endAdjust - end) * reduction); + } + if (dateAdjust >= endAdjust) // if the problem could not be resolved + continue; // we do not apply the changes and leave the milliseconds dates unaltered + + dateAtt.setValue(Double.toString(dateAdjust)); // set the milliseconds.date attribute + endAtt.setValue(Double.toString(endAdjust)); // set the milliseconds.date.end attribute } }