Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

# Emscripten disables exception catching by default; mx's internal MX_THROW
# (Throw.h) needs it, so DocumentManager can actually catch and convert it.
#
# Emscripten's default wasm stack is 64 KiB. mx's write path is a deep,
# unoptimized (Debug) C++ call chain -- DocumentManager -> ScoreWriter ->
# PartWriter -> MeasureWriter -> NoteWriter -> NotationsWriter, several of
# which carry their own sizable locals -- and it overflows that default with
# only a little headroom to spare (issue #389 hit this by adding two more
# spanner-writing loops). 1 MiB was measured to leave a comfortable margin
# for further growth in that same call chain.
if(EMSCRIPTEN)
add_compile_options(-fexceptions)
add_link_options(-fexceptions)
add_link_options(-fexceptions -sSTACK_SIZE=1048576)
endif()

option(MX_CORE_DEV "Build the core roundtrip (corert) test binary against the regenerated mx/core." OFF)
Expand Down
104 changes: 104 additions & 0 deletions src/include/mx/api/GlissandoData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// MusicXML Class Library
// Copyright (c) by Matthew James Briggs
// Distributed under the MIT License

#pragma once

#include "mx/api/ApiCommon.h"
#include "mx/api/Id.h"
#include "mx/api/LineData.h"
#include "mx/api/PositionData.h"
#include "mx/api/PrintData.h"
#include "mx/api/SpannerNumber.h"

#include <optional>
#include <string>

namespace mx
{
namespace api
{
// A glissando and a slide are notated the same way and carry the same attributes; they differ
// only in the pitch motion implied between the two notes they connect. A glissando sounds the
// discrete pitches in between (its line defaults to wavy); a slide is a continuous portamento
// (its line defaults to solid).
enum class GlissandoType
{
unspecified,
glissando,
slide
};

struct GlissandoStart
{
GlissandoType glissandoType;
SpannerNumber number;

// Text printed alongside the line, e.g. "gliss." -- the <glissando>/<slide> element value.
std::string text;

PositionData positionData;
PrintData printData; // font and color
LineData lineData; // line-type, dash-length, space-length

// Playback timing (MusicXML's trill-sound attributes). These exist on <slide> only -- a
// glissando has no accelerate/beats/first-beat/last-beat -- and are left at their defaults
// when glissandoType is glissando.
Bool accelerate;
std::optional<double> beats;
std::optional<double> firstBeat;
std::optional<double> lastBeat;

// The id attribute of the element this spanner end is written as -- <glissando> or <slide>
// (see Id.h).
std::optional<Id> id;

GlissandoStart(GlissandoType inGlissandoType)
: glissandoType{inGlissandoType}, number{}, text{}, positionData{}, printData{}, lineData{},
accelerate{Bool::unspecified}, beats{std::nullopt}, firstBeat{std::nullopt}, lastBeat{std::nullopt}, id{}
{
}
};

struct GlissandoStop
{
GlissandoType glissandoType;
SpannerNumber number;
PositionData positionData;
LineData lineData;

// The id attribute of the element this spanner end is written as -- <glissando> or <slide>
// (see Id.h).
std::optional<Id> id;

GlissandoStop(GlissandoType inGlissandoType)
: glissandoType{inGlissandoType}, number{}, positionData{}, lineData{}, id{}
{
}
};

MXAPI_EQUALS_BEGIN(GlissandoStart)
MXAPI_EQUALS_MEMBER(glissandoType)
MXAPI_EQUALS_MEMBER(number)
MXAPI_EQUALS_MEMBER(text)
MXAPI_EQUALS_MEMBER(positionData)
MXAPI_EQUALS_MEMBER(printData)
MXAPI_EQUALS_MEMBER(lineData)
MXAPI_EQUALS_MEMBER(accelerate)
MXAPI_EQUALS_MEMBER(beats)
MXAPI_EQUALS_MEMBER(firstBeat)
MXAPI_EQUALS_MEMBER(lastBeat)
MXAPI_EQUALS_MEMBER(id)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(GlissandoStart);

MXAPI_EQUALS_BEGIN(GlissandoStop)
MXAPI_EQUALS_MEMBER(glissandoType)
MXAPI_EQUALS_MEMBER(number)
MXAPI_EQUALS_MEMBER(positionData)
MXAPI_EQUALS_MEMBER(lineData)
MXAPI_EQUALS_MEMBER(id)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(GlissandoStop);
} // namespace api
} // namespace mx
1 change: 0 additions & 1 deletion src/include/mx/api/MarkData.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ enum class MarkType
invertedVerticalTurn,
haydn,
shake,
wavyLine,
mordent,
invertedMordent,
schleifer,
Expand Down
16 changes: 12 additions & 4 deletions src/include/mx/api/NoteAttachmentData.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#pragma once

#include "mx/api/CurveData.h"
#include "mx/api/GlissandoData.h"
#include "mx/api/MarkData.h"
#include "mx/api/TupletData.h"
#include "mx/api/WavyLineData.h"

namespace mx
{
Expand All @@ -21,8 +23,11 @@ class NoteAttachmentData
std::vector<CurveStop> curveStops;
std::vector<TupletStart> tupletStarts;
std::vector<TupletStop> tupletStops;
// std::vector<SpannerData> spannerStarts;
// std::vector<SpannerData> spannerStops;
std::vector<GlissandoStart> glissandoStarts;
std::vector<GlissandoStop> glissandoStops;
std::vector<WavyLineStart> wavyLineStarts;
std::vector<WavyLineContinue> wavyLineContinuations;
std::vector<WavyLineStop> wavyLineStops;
};

MXAPI_EQUALS_BEGIN(NoteAttachmentData)
Expand All @@ -32,8 +37,11 @@ MXAPI_EQUALS_MEMBER(curveContinuations)
MXAPI_EQUALS_MEMBER(curveStops)
MXAPI_EQUALS_MEMBER(tupletStarts)
MXAPI_EQUALS_MEMBER(tupletStops)
// MXAPI_EQUALS_MEMBER( spannerStarts )
// MXAPI_EQUALS_MEMBER( spannerStops )
MXAPI_EQUALS_MEMBER(glissandoStarts)
MXAPI_EQUALS_MEMBER(glissandoStops)
MXAPI_EQUALS_MEMBER(wavyLineStarts)
MXAPI_EQUALS_MEMBER(wavyLineContinuations)
MXAPI_EQUALS_MEMBER(wavyLineStops)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(NoteAttachmentData);
} // namespace api
Expand Down
134 changes: 134 additions & 0 deletions src/include/mx/api/WavyLineData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// MusicXML Class Library
// Copyright (c) by Matthew James Briggs
// Distributed under the MIT License

#pragma once

#include "mx/api/ApiCommon.h"
#include "mx/api/ColorData.h"
#include "mx/api/PositionData.h"
#include "mx/api/SpannerNumber.h"

#include <optional>
#include <string>

namespace mx
{
namespace api
{
// Which of the two notes flanking a trill or vibrato the wavy line's playback starts on.
enum class WavyLineStartNote
{
unspecified,
upper,
main,
below
};

// The written pitch step of the auxiliary (upper) note the trill alternates with.
enum class WavyLineTrillStep
{
unspecified,
whole,
half,
unison
};

// The interval of a trill's closing turn, or that it has none.
enum class WavyLineTwoNoteTurn
{
unspecified,
whole,
half,
none
};

// A wavy line indicates a trill extension or a vibrato line. Unlike glissando and slide it can
// have a continue point (for a line that crosses a system or page break), so it is a
// start/continue/stop spanner rather than a start/stop one. It lives inside a note's <ornaments>.
struct WavyLineStart
{
SpannerNumber number;
PositionData positionData; // placement rides in positionData.placement
bool isColorSpecified;
ColorData colorData;

// A specific SMuFL glyph from the Multi-segment lines range (e.g. "wiggleTrill"), overriding
// the default trill/vibrato glyph.
std::optional<std::string> smufl;

// Playback (MusicXML's trill-sound attributes).
WavyLineStartNote startNote;
WavyLineTrillStep trillStep;
WavyLineTwoNoteTurn twoNoteTurn;
Bool accelerate;
std::optional<double> beats;
std::optional<double> secondBeat;
std::optional<double> lastBeat;

WavyLineStart()
: number{}, positionData{}, isColorSpecified{false}, colorData{}, smufl{std::nullopt},
startNote{WavyLineStartNote::unspecified}, trillStep{WavyLineTrillStep::unspecified},
twoNoteTurn{WavyLineTwoNoteTurn::unspecified}, accelerate{Bool::unspecified}, beats{std::nullopt},
secondBeat{std::nullopt}, lastBeat{std::nullopt}
{
}
};

struct WavyLineContinue
{
SpannerNumber number;
PositionData positionData;
bool isColorSpecified;
ColorData colorData;

WavyLineContinue() : number{}, positionData{}, isColorSpecified{false}, colorData{}
{
}
};

struct WavyLineStop
{
SpannerNumber number;
PositionData positionData;
bool isColorSpecified;
ColorData colorData;

WavyLineStop() : number{}, positionData{}, isColorSpecified{false}, colorData{}
{
}
};

MXAPI_EQUALS_BEGIN(WavyLineStart)
MXAPI_EQUALS_MEMBER(number)
MXAPI_EQUALS_MEMBER(positionData)
MXAPI_EQUALS_MEMBER(isColorSpecified)
MXAPI_EQUALS_MEMBER(colorData)
MXAPI_EQUALS_MEMBER(smufl)
MXAPI_EQUALS_MEMBER(startNote)
MXAPI_EQUALS_MEMBER(trillStep)
MXAPI_EQUALS_MEMBER(twoNoteTurn)
MXAPI_EQUALS_MEMBER(accelerate)
MXAPI_EQUALS_MEMBER(beats)
MXAPI_EQUALS_MEMBER(secondBeat)
MXAPI_EQUALS_MEMBER(lastBeat)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(WavyLineStart);

MXAPI_EQUALS_BEGIN(WavyLineContinue)
MXAPI_EQUALS_MEMBER(number)
MXAPI_EQUALS_MEMBER(positionData)
MXAPI_EQUALS_MEMBER(isColorSpecified)
MXAPI_EQUALS_MEMBER(colorData)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(WavyLineContinue);

MXAPI_EQUALS_BEGIN(WavyLineStop)
MXAPI_EQUALS_MEMBER(number)
MXAPI_EQUALS_MEMBER(positionData)
MXAPI_EQUALS_MEMBER(isColorSpecified)
MXAPI_EQUALS_MEMBER(colorData)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(WavyLineStop);
} // namespace api
} // namespace mx
18 changes: 9 additions & 9 deletions src/private/mx/api/MarkData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ bool isMarkOrnament(MarkType markType)
return (markType == MarkType::trillMark) || (markType == MarkType::turn) || (markType == MarkType::delayedTurn) ||
(markType == MarkType::invertedTurn) || (markType == MarkType::delayedInvertedTurn) ||
(markType == MarkType::verticalTurn) || (markType == MarkType::invertedVerticalTurn) ||
(markType == MarkType::haydn) || (markType == MarkType::shake) || (markType == MarkType::wavyLine) ||
(markType == MarkType::mordent) || (markType == MarkType::invertedMordent) ||
(markType == MarkType::schleifer) || (markType == MarkType::tremoloSingleOne) ||
(markType == MarkType::tremoloSingleTwo) || (markType == MarkType::tremoloSingleThree) ||
(markType == MarkType::tremoloSingleFour) || (markType == MarkType::tremoloSingleFive) ||
(markType == MarkType::tremoloSingleSix) || (markType == MarkType::tremoloSingleSeven) ||
(markType == MarkType::tremoloSingleEight) || (markType == MarkType::tremoloStart) ||
(markType == MarkType::tremoloStop) || (markType == MarkType::tremoloUnmeasured) ||
(markType == MarkType::otherOrnament) || (markType == MarkType::unknownOrnament);
(markType == MarkType::haydn) || (markType == MarkType::shake) || (markType == MarkType::mordent) ||
(markType == MarkType::invertedMordent) || (markType == MarkType::schleifer) ||
(markType == MarkType::tremoloSingleOne) || (markType == MarkType::tremoloSingleTwo) ||
(markType == MarkType::tremoloSingleThree) || (markType == MarkType::tremoloSingleFour) ||
(markType == MarkType::tremoloSingleFive) || (markType == MarkType::tremoloSingleSix) ||
(markType == MarkType::tremoloSingleSeven) || (markType == MarkType::tremoloSingleEight) ||
(markType == MarkType::tremoloStart) || (markType == MarkType::tremoloStop) ||
(markType == MarkType::tremoloUnmeasured) || (markType == MarkType::otherOrnament) ||
(markType == MarkType::unknownOrnament);
}

bool isMarkFermata(MarkType markType)
Expand Down
1 change: 0 additions & 1 deletion src/private/mx/impl/Converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ const Converter::EnumMap<core::OrnamentsGroupChoice::Kind, api::MarkType> Conver
{core::OrnamentsGroupChoice::Kind::invertedVerticalTurn, api::MarkType::invertedVerticalTurn},
{core::OrnamentsGroupChoice::Kind::haydn, api::MarkType::haydn},
{core::OrnamentsGroupChoice::Kind::shake, api::MarkType::shake},
{core::OrnamentsGroupChoice::Kind::wavyLine, api::MarkType::wavyLine},
{core::OrnamentsGroupChoice::Kind::mordent, api::MarkType::mordent},
{core::OrnamentsGroupChoice::Kind::invertedMordent, api::MarkType::invertedMordent},
{core::OrnamentsGroupChoice::Kind::schleifer, api::MarkType::schleifer},
Expand Down
Loading
Loading