Introduced MEI ornament expansions and their conversion to MPM ornamentation - #33
Introduced MEI ornament expansions and their conversion to MPM ornamentation#33LarsEngeln wants to merge 129 commits into
Conversation
…has a certain value, find sibling, including a simple way to add a short UUID
…nctions, where MeiElement is more abstract
…o be played as <supplied>. Mainly this is for rendering via MPM.
…dict) that is used by the MeiInstructifier
…ion of halfsteps between two note. "intm" is now in halfsteps, not interval anymore
|
|
|
|
|
…g a Context interface and renaming Mei/MsmElement to more precise Mei/Msm/NoteElement
…es only), and changes the OrnamentProcessor to only use MeiElementHelper (instead of Helper./XOM directly)
| * @param chord an mei chord, bTrem or fTrem element | ||
| */ | ||
| private void processChord(Element chord) { | ||
| public void processChord(Element chord) { |
There was a problem hiding this comment.
Not public. If private is too strict use protected.
| } | ||
| } | ||
|
|
||
| public MsmNoteElement meiNote2MsmNote(MeiElementHelper meiNote) { |
There was a problem hiding this comment.
Not public!
Missing documentationen above method header.
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
|
|
||
| public interface Context { |
|
|
||
| public class Mei extends meico.xml.XmlBase implements Cloneable { | ||
|
|
||
| boolean areOrnamentsExpanded = false; |
There was a problem hiding this comment.
Still, this should be removed.
| * @return 'this' Mei for chaining | ||
| */ | ||
| public Mei expandOrnaments() { | ||
| if(areOrnamentsExpanded) |
There was a problem hiding this comment.
Unnecessary. If the application wants this to be done twice, it should be allowed.
| * This class interfaces temporal domain with a value | ||
| * @author Lars Engeln | ||
| */ | ||
| public class TemporalValue { |
There was a problem hiding this comment.
Lots of missing documentation in this class. What is the meaning of the class variables? Please also document all methods.
| @@ -0,0 +1,549 @@ | |||
| package meico.mpm.elements; | |||
There was a problem hiding this comment.
This is the wrong place for this class. We need to discuss this.
| return getDomain() == Domain.Ticks; | ||
| } | ||
|
|
||
| /** TODO |
|
|
||
| double greaterValue = getValue(); | ||
| double lesserValue = value; | ||
| if(getValue() < value) { |
There was a problem hiding this comment.
Put the above two lines in an else, so the value assignments are done only once.
| } | ||
| /** | ||
| * returns if the relation stack has an absolute root | ||
| */ |
There was a problem hiding this comment.
Pull request overview
This PR introduces an end-to-end pipeline for expanding MEI ornaments into explicit note material (<supplied>/<graceGrp>) and converting that information into MPM ornamentation data, including new temporal-domain handling for ornament timing/spread.
Changes:
- Added MEI ornament expansion/preprocessing (
meico.mei.ornament) plus conversion support into MPMornamentationMap. - Introduced new XML helper abstractions (
RichElement,MeiElementHelper,MsmNoteElement) and additional MEI helper utilities. - Extended ornamentation/temporal rendering capabilities (relative/ticks/ms domains, alignment “at start/end”, tremolo support, multi-ornament distribution).
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/resources/ornaments.dict | Adds ornament name → pitch-alteration patterns used for ornament expansion/matching. |
| src/meico/xml/RichElement.java | Introduces an OO wrapper around XOM Element with attribute/child/id utilities. |
| src/meico/supplementary/Stopwatch.java | Adds a simple stopwatch utility for console timing output. |
| src/meico/msm/MsmNoteElement.java | Adds MSM-focused RichElement wrapper utilities for note access/comparison. |
| src/meico/msm/Msm.java | Extends expressive MIDI export API and clamps negative dates during MIDI event creation. |
| src/meico/mpm/elements/TemporalValue.java | Adds temporal value abstraction with unit/domain parsing and relative/absolute operations. |
| src/meico/mpm/elements/styles/defs/OrnamentDef.java | Extends ornament temporal spread model (TemporalValue, alignment) and render logic. |
| src/meico/mpm/elements/Performance.java | Wires ornament expansion/rendering into performance pipeline; attempts map cloning. |
| src/meico/mpm/elements/maps/OrnamentationMap.java | Major rework: supports child notes/repetitions, note generation, grouping/spacing logic. |
| src/meico/mpm/elements/maps/GenericMap.java | Adds removeElement(String id) convenience removal by xml:id. |
| src/meico/mpm/elements/maps/data/OrnamentData.java | Extends ornament data to include correspondence, notes, repetitions, and new apply API. |
| src/meico/mpm/elements/maps/ArticulationMap.java | Adds articulation lookup/copy helper for ornament-generated notes. |
| src/meico/mei/ornament/package-info.java | Adds package docs for new ornament subpackage. |
| src/meico/mei/ornament/OrnamentProcessor.java | Implements MEI→MPM ornament extraction from generated <supplied> expansions. |
| src/meico/mei/ornament/OrnamentExpansion.java | Defines the in-memory model for generated ornament expansions and merge behavior. |
| src/meico/mei/ornament/OrnamentExpander.java | Adds MEI preprocessing step that generates <supplied> ornament expansions. |
| src/meico/mei/NoteProcessor.java | Introduces interface to decouple note/chord processing for ornament processors. |
| src/meico/mei/MeiElementHelper.java | Adds MEI-specific wrapper over RichElement (namespace + .ges fallback). |
| src/meico/mei/Mei2MsmMpmConverter.java | Integrates ornament processor; exposes context/hooks for ornament conversion. |
| src/meico/mei/Mei.java | Adds expandOrnaments() and export flag to optionally bypass ornament expansion. |
| src/meico/mei/Helper.java | Adds multiple MEI XML utilities and pitch/interval helper functions. |
| src/meico/mei/Context.java | Adds context interface used by ornament processing to access converter state. |
| src/meico/mei/AttributesWithIds.java | Adjusts visibility (package-private). |
| README.md | Updates contributors and adds CLI flag --ignore-ornaments; updates formatting/content. |
| MEI2MSM_Coverage_Documentation.md | Updates documentation to reflect new ornament/grace/tremolo preprocessing behavior. |
| history.md | Adds v0.11.15 changelog documenting the ornament/temporal spread feature set. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| Pattern pattern = Pattern.compile("^(\\d+)(ms|th|%|ticks|\\?)$"); // checks string if it is a valid value + unit string | ||
| Matcher m = pattern.matcher(valueDomain.trim()); | ||
| if (m.matches()) { | ||
| setValue(Double.parseDouble(m.group(1))); | ||
| setDomain(fromDomainString(m.group(2))); | ||
| return; | ||
| } |
| dateAttName = "ornament.milliseconds.date.offset"; | ||
| durAttName = "ornament.milliseconds.duration"; |
| ornament.copyValue("date", principalNote); | ||
| ArrayList<MsmNoteElement> children = ornament.getChildrenAsMsmElements(); | ||
| ArrayList<String> noteOrder = new ArrayList<>(Arrays.asList(ornament.get("note.order").replaceAll(":\\|:", ":| |:").split(" "))); | ||
| Map<Integer, Integer> repeats = new HashMap<>(); |
| this.notes = new ArrayList<>(); | ||
| xml.getChildElements("ornamentNote").forEach(note -> { this.notes.add(note); }); |
| try { | ||
| ornamentationMap = OrnamentationMap.createOrnamentationMap((OrnamentationMap) mpmPart.getDated().getMap(Mpm.ORNAMENTATION_MAP)); // get ornamentationMap | ||
| } | ||
| catch (Exception e) { | ||
| String exc = e.getLocalizedMessage(); | ||
| } |
| String ornamFullName = getOrnamentFullName(ornament); | ||
| if(ornamFullName == null || ornamFullName.equals("")) | ||
| return; // if I am not yet supported |
| od.xmlId = correspId != null ? correspId : UUID.randomUUID().toString(); | ||
| od.correspondence = elementId; | ||
| od.date = (Double) timingData.get(0); | ||
| od.ornamentDefName = segmentLabels.get(s); |
| /** | ||
| * returns halfsteps between pname1 and pname2 (always positive) | ||
| * @param pname1 | ||
| * @param pname2 | ||
| * @return | ||
| */ | ||
| public static int getHalfstepsBetween(String pname1, String pname2) { | ||
| return Math.abs(getHalfstepsFromC(pname2) - getHalfstepsFromC(pname1)); | ||
| } |
| dateEnd = Math.round(Double.parseDouble(endAtt.getValue())); | ||
| if(dateEnd < 0) { | ||
| dateEnd = -(date-dateEnd); | ||
| } |
| public Map<String, ArrayList<String>> renderGlobalOrnamentationMap(ArrayList<GenericMap> maps) { | ||
| if ((maps == null) || maps.isEmpty()) | ||
| return; | ||
| return new HashMap<>(); | ||
|
|
||
| this.apply(maps); | ||
| return new HashMap<>(); // this.apply(maps); | ||
| } |
v0.11.15
Introduced MEI ornament expansions and their conversion to MPM ornamentation.